[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-ai-rewrites-postgresql-in-rust-en":3,"article-related-ai-rewrites-postgresql-in-rust-en":30,"series-tools-b29c9a4b-0350-4171-9c68-cd8c633b7593":79},{"id":4,"slug":5,"title":6,"content":7,"summary":8,"source":9,"source_url":10,"author":11,"image_url":12,"cover_image":12,"category":13,"language":14,"translated_content":11,"related_article_id":15,"keywords":16,"key_takeaways":22,"views":26,"created_at":27,"published_at":28,"topic_cluster_id":29},"b29c9a4b-0350-4171-9c68-cd8c633b7593","ai-rewrites-postgresql-in-rust-en","How AI Rewrites PostgreSQL in Rust","\u003Cp data-speakable=\"summary\">I used to translate legacy C by hand; this workflow turns PostgreSQL into \u003Ca href=\"\u002Ftag\u002Frust\">Rust\u003C\u002Fa> with c2rust, then \u003Ca href=\"\u002Ftag\u002Fclaude\">Claude\u003C\u002Fa> cleans it up crate by crate.\u003C\u002Fp>\u003Cp>I've been around enough old C codebases to know the smell. You open one file, and before long you're three layers deep in macros, pointer tricks, and comments that basically say, “good luck.” If you want Rust out of that mess, the usual plan is heroic and miserable: rewrite a subsystem, pray you didn't miss a lifetime edge, then spend the next month untangling the fallout. That is exactly why this PostgreSQL story caught my attention. It doesn't start with purity. It starts with a mechanical translation that is ugly but runnable, which is honestly the only sane way to begin.\u003C\u002Fp>\u003Cp>The part that changed my mind is not that AI wrote Rust. I've seen enough demos to be skeptical of that headline. The interesting part is that the author stopped treating the model like a magic rewrite button and turned it into a boring pipeline: translate first, then clean up one crate at a time, then audit the result. That is much closer to how I would actually trust a large legacy migration. The source that kicked this off is a Zhihu post at \u003Ca href=\"https:\u002F\u002Fzhuanlan.zhihu.com\u002Fp\u002F2060038538951910350\">zhuanlan.zhihu.com\u002Fp\u002F2060038538951910350\u003C\u002Fa>, which summarizes a second attempt that started on June 12 and uses \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fimmunant\u002Fc2rust\">c2rust\u003C\u002Fa> plus \u003Ca href=\"https:\u002F\u002Fclaude.ai\u002F\">Claude\u003C\u002Fa> to refactor PostgreSQL piece by piece.\u003C\u002Fp>\u003Ch2>Stop asking AI to be clever before the code even runs\u003C\u002Fh2>\u003Cblockquote>先用 c2rust 把 PostgreSQL 的 C 源码 机械翻译 成 Rust，得到一批虽然充斥 unsafe，却已经能跑 PG 核心 SQL 回归测试的代码。\u003C\u002Fblockquote>\u003Cp>What this actually means is: don’t start with “write idiomatic Rust.” Start with “make the code compile and behave the same way.” That sounds less glamorous because it is. But I’ve watched enough migrations die on the hill of premature elegance. If the first pass preserves behavior, even with ugly \u003Ccode>unsafe\u003C\u002Fcode> everywhere, you’ve bought yourself something valuable: a testable baseline.\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784709243935-mcwk.png\" alt=\"How AI Rewrites PostgreSQL in Rust\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>I ran into this exact pattern when helping move a gnarly C module into Rust. The first version was offensive to every Rust instinct I had. It had raw pointers, awkward wrappers, and enough \u003Ccode>unsafe\u003C\u002Fcode> to make \u003Ca href=\"\u002Ftag\u002Fcode-review\">code review\u003C\u002Fa> feel like a liability exercise. But it passed the existing tests, and that changed the conversation. Once behavior was locked down, the cleanup became mechanical instead of philosophical.\u003C\u002Fp>\u003Cp>How to apply it: use a translator like \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fimmunant\u002Fc2rust\">c2rust\u003C\u002Fa> to get a runnable Rust skeleton, then immediately wire it to the strongest tests you have. If you don’t have tests, build the smallest repeatable harness you can. For PostgreSQL, that meant core SQL regression tests. For your codebase, it might be integration tests, golden files, or a narrow \u003Ca href=\"\u002Ftag\u002Fbenchmark\">benchmark\u003C\u002Fa> suite. The point is to anchor the translation in observed behavior before you let anyone, human or model, “improve” the design.\u003C\u002Fp>\u003Cul>\u003Cli>Translate first, refactor later.\u003C\u002Fli>\u003Cli>Use tests as the contract, not vibes.\u003C\u002Fli>\u003Cli>Accept ugly \u003Ccode>unsafe\u003C\u002Fcode> if it keeps the system honest.\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>Split the monolith into pieces the model can actually hold\u003C\u002Fh2>\u003Cp>The next move is the one people skip when they try to use AI on a giant repo: break the system into small units that fit inside a reviewable loop. The post says PostgreSQL was split into roughly one thousand crates. That number matters less as a precise statistic and more as a signal. The work was decomposed until each chunk was small enough to reason about, rewrite, and audit without turning the whole effort into a fog machine.\u003C\u002Fp>\u003Cp>What this actually means is that the model is not being asked to understand “PostgreSQL.” It is being asked to understand one crate, one boundary, one local set of dependencies. That is a much more realistic task. I’ve seen teams hand a model a giant folder tree and then act surprised when the output is incoherent. Of course it is. The model is not a senior architect with months of context. It is a fast pattern machine. Give it a smaller surface area and it behaves a lot better.\u003C\u002Fp>\u003Cp>I like this part because it mirrors how I would do a human rewrite, just faster. I would not assign one engineer “rewrite the database.” I would assign a module, a contract, and a checklist. If you can’t describe the unit of work in a sentence, it’s too big for AI to touch safely.\u003C\u002Fp>\u003Cp>How to apply it: define module boundaries before you prompt anything. In Rust terms, crates are a natural seam. In other languages, that might be packages, libraries, or folders with explicit public APIs. Then make a rule: one pass, one unit, one audit. If the model starts wandering across boundaries, stop it and shrink the target.\u003C\u002Fp>\u003Cul>\u003Cli>Smaller units produce better model output.\u003C\u002Fli>\u003Cli>Boundaries reduce accidental rewrites.\u003C\u002Fli>\u003Cli>One module per cycle keeps review sane.\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>Make the workflow boring on purpose\u003C\u002Fh2>\u003Cblockquote>流水线只有三步：挑下一个 crate、重写、审计。\u003C\u002Fblockquote>\u003Cp>That three-step loop is the part I trust most. It is painfully unsexy, which is usually a good sign. Pick the next crate. Rewrite it. Audit it. Repeat. There’s no “let’s have the model redesign the architecture.” There’s no “maybe it can infer the intent of the whole system.” Just a tight operational loop.\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784709253262-5jx5.png\" alt=\"How AI Rewrites PostgreSQL in Rust\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>What this actually means is the AI is being used as a very fast pair programmer, not as a free-roaming \u003Ca href=\"\u002Ftag\u002Fagent\">agent\u003C\u002Fa> with a blank check. I’ve been burned by the opposite setup. You give a model \u003Ca href=\"\u002Fnews\u002Fkimi-k3-intelligence-performance-price-analysis-en\">too much\u003C\u002Fa> freedom, it produces a lot of text, and you spend your time sorting confident nonsense from useful edits. A constrained loop reduces the blast radius. It also makes it easier to stop and inspect where the quality drops.\u003C\u002Fp>\u003Cp>The audit step matters more than people want to admit. If you skip it, you’re not doing migration; you’re doing content generation with source code. An audit can be code review, static analysis, test runs, or all three. In a database codebase, I would want both semantic checks and a very boring human read-through of the changed crate. Yes, it takes time. So does debugging a subtle storage bug later.\u003C\u002Fp>\u003Cp>How to apply it: write the loop down before you start. For example: select module, generate refactor, run tests, inspect diff, approve or revert. If you’re using an LLM, keep the prompt narrow and repeatable. If the audit fails twice in a row, don’t keep prompting harder. Shrink the module or change the transformation goal.\u003C\u002Fp>\u003Ch2>Let generated code stay ugly where it needs to\u003C\u002Fh2>\u003Cp>The post notes that most crates went through the process, but some generated modules like the parser still keep a lot of mechanically translated code and \u003Ccode>unsafe\u003C\u002Fcode>. I think that’s the right call, and I wish more teams were honest enough to say it out loud. Not every part of a system deserves the same treatment. Some pieces are basically glue around a generated grammar or a low-level data structure. For those, “idiomatic Rust” may be less important than “don’t break the parser.”\u003C\u002Fp>\u003Cp>What this actually means is you should optimize for risk, not aesthetics. I’ve seen people waste weeks trying to make generated code pretty. That is usually a bad trade. If a module is stable, generated, and already well-understood, leaving it mechanically translated may be the cheapest correct answer. Save the cleanup energy for code that benefits from human-shaped refactoring.\u003C\u002Fp>\u003Cp>This is where Rust culture can get a little self-defeating. We like clean ownership graphs and elegant abstractions, which is fine until that preference starts fighting the migration. The goal is not to make every line feel native on day one. The goal is to get the system into a state where you can safely improve the parts that matter most.\u003C\u002Fp>\u003Cp>How to apply it: classify modules before refactoring them. Put them into buckets like “must be idiomatic,” “safe enough as generated code,” and “leave alone unless tests fail.” Then spend your attention accordingly. If a generated parser is stable and ugly, that may be acceptable. If a storage path is ugly, that is a different story.\u003C\u002Fp>\u003Ch2>Audit like a skeptic, not like a fan\u003C\u002Fh2>\u003Cp>The whole approach only works if the audit is real. And by real, I mean someone is actually checking whether the transformed crate still behaves like the original. The article’s workflow makes audit a first-class step, which is exactly where it belongs. I’ve seen too many AI-assisted code changes get waved through because the diff looked “reasonable.” Reasonable is not a verification strategy.\u003C\u002Fp>\u003Cp>What this actually means is you need multiple kinds of confidence. Tests tell you the behavior still lines up. Static analysis tells you whether the rewrite introduced obvious footguns. Human review tells you whether the model quietly changed semantics while making the code prettier. You want all three if the code matters.\u003C\u002Fp>\u003Cp>My own rule is simple: if a model touched control flow, memory handling, or boundary conditions, I read the diff like I expect it to be wrong. That is not cynicism. That is discipline. Models are good at local transformations and bad at knowing which local change has global consequences. The audit is where you catch that mismatch.\u003C\u002Fp>\u003Cp>How to apply it: make the audit checklist explicit. Check invariants, compare outputs, inspect unsafe blocks, and verify public APIs did not drift. If you can automate part of that, do it. If not, at least standardize the review questions so every crate gets the same scrutiny.\u003C\u002Fp>\u003Ch2>Why this worked better than the usual AI rewrite fantasy\u003C\u002Fh2>\u003Cp>The reason this second version feels more credible than the typical “AI rewrote X” story is that it respects the shape of the problem. PostgreSQL is huge. C to Rust is not a style conversion; it is a semantic migration across memory models, ownership rules, and decades of accumulated assumptions. The workflow doesn’t pretend that the model understands all of that in one shot.\u003C\u002Fp>\u003Cp>What this actually means is the author used AI where it is strongest: repetitive, bounded, transformation-heavy work. That is the sweet spot. c2rust handles the mechanical translation. Claude handles the local cleanup. Humans handle boundaries, audits, and the judgment calls. Nobody is pretending one tool can do the whole job.\u003C\u002Fp>\u003Cp>I find that honest division of labor refreshing. It’s also the only version I would recommend to a team that cares about correctness. If you’re trying to migrate a serious codebase, the lesson is not “let AI write everything.” The lesson is “design the pipeline so AI can safely do the tedious middle of the work.”\u003C\u002Fp>\u003Cp>How to apply it: think in phases. Phase one preserves behavior. Phase two improves readability. Phase three tightens safety and removes leftover translation artifacts. If you try to collapse those into one prompt, you’re asking for a mess. If you separate them, you get something you can actually ship.\u003C\u002Fp>\u003Ch2>The template you can copy\u003C\u002Fh2>\u003Cpre>\u003Ccode>Legacy C to Rust migration workflow for large codebases\n\nGoal:\n- Preserve behavior first.\n- Improve Rust idioms second.\n- Audit every change before merge.\n\nPhase 1: Mechanical translation\n1. Use c2rust to translate the target C module or subsystem into Rust.\n2. Keep the output even if it contains many unsafe blocks.\n3. Compile immediately and run the existing regression or integration tests.\n4. Do not refactor for style in this phase.\n\nPhase 2: Decompose the codebase\n1. Split the translated system into small crates, packages, or modules.\n2. Make each unit small enough for one prompt, one review, and one test run.\n3. Prefer boundaries that match existing APIs or internal subsystems.\n4. Avoid cross-cutting rewrites.\n\nPhase 3: AI-assisted cleanup loop\nFor each unit:\n- Select one crate\u002Fmodule.\n- Ask the model to rewrite only that unit.\n- Keep the prompt narrow:\n  - preserve behavior\n  - reduce unsafe where possible\n  - improve naming and structure\n  - do not change public APIs unless requested\n- Run tests.\n- Inspect the diff.\n- Approve only if behavior and invariants still hold.\n\nAudit checklist:\n- Does the code still pass the relevant tests?\n- Did control flow change in a way that could alter semantics?\n- Are unsafe blocks still necessary?\n- Did any public interface drift?\n- Are generated or parser-like modules acceptable to leave partially mechanical if they are stable?\n\nPrompt template:\n\"Refactor this Rust module while preserving behavior exactly.\nKeep the public API unchanged unless I explicitly ask otherwise.\nReduce obvious translation artifacts and unnecessary unsafe where safe.\nDo not touch unrelated files.\nReturn only the revised code and a short list of behavior-sensitive changes.\"\n\nReview rule:\n- If the diff is hard to explain in one paragraph, the unit is too big.\n- If tests fail twice, shrink the unit.\n- If the module is generated or low-risk, leaving some mechanical code is acceptable.\n- If the module handles memory, parsing, or storage, review it as if the model made a mistake.\n\nStop condition:\n- The module compiles.\n- The tests pass.\n- The diff is understandable.\n- The remaining unsafe is justified.\n- The code is good enough to ship, not perfect enough to admire.\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>That template is the real takeaway for me. It turns a flashy AI claim into a workflow I can actually imagine using on a nasty legacy repo. The trick is not to ask the model for brilliance. The trick is to give it a narrow lane, a test harness, and a human who is willing to say no.\u003C\u002Fp>\u003Cp>Source attribution: this breakdown is based on the Zhihu post at \u003Ca href=\"https:\u002F\u002Fzhuanlan.zhihu.com\u002Fp\u002F2060038538951910350\">https:\u002F\u002Fzhuanlan.zhihu.com\u002Fp\u002F2060038538951910350\u003C\u002Fa>. I’ve added the framing, examples, and template; the underlying idea comes from the author’s description of the second attempt and the HN explanation they referenced.\u003C\u002Fp>","A practical breakdown of turning PostgreSQL’s C into Rust with c2rust, then cleaning it up crate by crate with Claude.","zhuanlan.zhihu.com","https:\u002F\u002Fzhuanlan.zhihu.com\u002Fp\u002F2060038538951910350",null,"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784709243935-mcwk.png","tools","en","8ef02ef4-2a57-4db0-8f87-0705cbf6e1ac",[17,18,19,20,21],"PostgreSQL","Rust","c2rust","Claude","legacy migration",[23,24,25],"Mechanical translation first, idiomatic cleanup later.","Small crates make AI-assisted refactoring reviewable.","Audit is non-negotiable when models touch real code.",0,"2026-07-22T08:33:28.280911+00:00","2026-07-22T08:33:28.275+00:00","1369778c-5e6f-4dfa-8ede-1d5034f92fcc",{"tags":31,"relatedLang":38,"relatedPosts":42},[32,34,36],{"name":18,"slug":33},"rust",{"name":20,"slug":35},"claude",{"name":17,"slug":37},"postgresql",{"id":15,"slug":39,"title":40,"language":41},"three-step-postgresql-c-to-rust-rewrite-zh","三步把 PostgreSQL C 改成 Rust","zh",[43,49,55,61,67,73],{"id":44,"slug":45,"title":46,"cover_image":47,"image_url":47,"created_at":48,"category":13},"93d495f8-e764-4dd2-9c49-946f1f91c909","ai-agent-tooling-docs-into-workflows-en","AI Agent tooling that turns docs into workflows","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784707449888-f5dh.png","2026-07-22T08:03:27.861717+00:00",{"id":50,"slug":51,"title":52,"cover_image":53,"image_url":53,"created_at":54,"category":13},"41d705ff-ae43-457b-be0c-626acf99abfd","docker-desktop-windows-install-flow-en","Docker Desktop on Windows in one clean install flow","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784656997287-5hio.png","2026-07-21T18:02:37.402109+00:00",{"id":56,"slug":57,"title":58,"cover_image":59,"image_url":59,"created_at":60,"category":13},"24569438-14fd-4295-99a5-145c6846b030","grok-4-5-cursor-launch-benchmarks-pricing-en","Grok 4.5 hits Cursor with $2\u002F$6 pricing","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784536369476-at9z.png","2026-07-20T08:32:24.692259+00:00",{"id":62,"slug":63,"title":64,"cover_image":65,"image_url":65,"created_at":66,"category":13},"6bc7f633-a474-417a-9dbe-d4fbc46e3e61","agt-governed-agent-calls-en","AGT turns agent calls into governed actions","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784405021642-7891.png","2026-07-18T20:03:17.886807+00:00",{"id":68,"slug":69,"title":70,"cover_image":71,"image_url":71,"created_at":72,"category":13},"7f260a96-7ecb-4379-8fa4-ea0854c1fa06","openclaw-v2026-7-1-control-ui-workspace-en","OpenClaw v2026.7.1 turns control UI into a workspace","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784358239202-kzmg.png","2026-07-18T07:03:26.009425+00:00",{"id":74,"slug":75,"title":76,"cover_image":77,"image_url":77,"created_at":78,"category":13},"9d707772-c135-4706-889f-e36ca09cd4ae","openai-screenless-speaker-turns-chatgpt-companion-en","OpenAI’s screenless speaker turns ChatGPT into a companion","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1784289805829-eiuq.png","2026-07-17T12:02:53.86563+00:00",[80,85,90,95,100,105,110,115,120,125],{"id":81,"slug":82,"title":83,"created_at":84},"8008f1a9-7a00-4bad-88c9-3eedc9c6b4b1","surepath-ai-mcp-policy-controls-en","SurePath AI's New MCP Policy Controls Enhance AI Security","2026-03-26T01:26:52.222015+00:00",{"id":86,"slug":87,"title":88,"created_at":89},"27e39a8f-b65d-4f7b-a875-859e2b210156","mcp-standard-ai-tools-2026-en","MCP Standard in 2026: Integrating AI Tools","2026-03-26T01:27:43.127519+00:00",{"id":91,"slug":92,"title":93,"created_at":94},"165f9a19-c92d-46ba-b3f0-7125f662921d","rag-2026-transforming-enterprise-ai-en","How RAG in 2026 is Transforming Enterprise AI","2026-03-26T01:28:11.485236+00:00",{"id":96,"slug":97,"title":98,"created_at":99},"6a2a8e6e-b956-49d8-be12-cc47bdc132b2","mastering-ai-prompts-2026-guide-en","Mastering AI Prompts: A 2026 Guide for Developers","2026-03-26T01:29:07.835148+00:00",{"id":101,"slug":102,"title":103,"created_at":104},"3ab2c67e-4664-4c67-a013-687a2f605814","garry-tan-open-sources-claude-code-toolkit-en","Garry Tan Open-Sources a Claude Code Toolkit","2026-03-26T08:26:20.245934+00:00",{"id":106,"slug":107,"title":108,"created_at":109},"66a7cbf8-7e76-41d4-9bbf-eaca9761bf69","github-ai-projects-to-watch-in-2026-en","20 GitHub AI Projects to Watch in 2026","2026-03-26T08:28:09.752027+00:00",{"id":111,"slug":112,"title":113,"created_at":114},"9f332fda-eace-448a-a292-2283951eee71","practical-github-guide-learning-ml-2026-en","A Practical GitHub Guide to Learning ML in 2026","2026-03-27T01:16:50.125678+00:00",{"id":116,"slug":117,"title":118,"created_at":119},"1b1f637d-0f4d-42bd-974b-07b53829144d","aiml-2026-student-ai-ml-lab-repo-review-en","AIML-2026 Is a Bare-Bones Student Lab Repo","2026-03-27T01:21:51.661231+00:00",{"id":121,"slug":122,"title":123,"created_at":124},"6d1bf3f6-e191-4d30-b55b-8a0722fa6afe","ai-trending-github-repos-and-research-feeds-en","AI Trending Tracks Repos and Research Feeds","2026-03-27T01:31:35.709532+00:00",{"id":126,"slug":127,"title":128,"created_at":129},"010539a1-4c3a-4bd3-937a-26616422ee0d","awesome-ai-for-science-research-tools-map-en","Awesome AI for Science Is Becoming a Real Research Map","2026-03-27T01:46:50.89513+00:00"]