Postgres rewritten in Rust, now passing 100% of the Postgres regression tests
github.com
github.com
To concisely give an overview of the project, I've been experimenting with using LLMs to build a better version of Postgres. Postgres is 30 years old and we've learned a lot about databases since hten. A lot of the techniques that work for doing a rewrite are also useful for doing a rearchitecture.
I'm now working on a new, not yet published version of pgrust that incorporates a lot of techniques. Currently the new version:
- Passes 100% of Postgres regression suite
- Implements a thread per connection model instead of the process per connection model Postgres does
- Is 50% faster than Postgres on transaction workloads
- Is ~300x faster than Postgres on analytical workloads. Right now it's 2x slower than Clickhouse on clickbench and I think it's possible to get faster than Clickhouse
If you have any questions, I'm happy to answer them.I know you say it's not production ready and not optimized yet, but in the same breath - in your comment here - you say it's already faster.
[0] https://github.com/Percona-Lab/sysbench-tpccThat sounds like you are storing the data in a columnar format? Or do you do both row and columnar?
In a somewhat similar (yet also quite different) effort, I've been working on δx, a Postgres extension that compresses the data in a columnar format stored in normal Postgres tables (so replication, crash recovery, pg_dump, etc. still work normally). https://github.com/xataio/deltax
It is currently about 30-40% slower than ClickHouse (single node, ofc). The PR to add it to clickbench was just accepted, so you can see the comparison here: https://benchmark.clickhouse.com/#system=+liH|_etx|gQ|saB&ty...
pg_lake also uses DuckDB but keeps it external, routing through Postgres and managing Iceberg tables (but not the data itself) there (https://github.com/Snowflake-Labs/pg_lake).
Both of these were neck and neck with ClickHouse last time I tried them.
Plus all the normal Postgres features work as expected: physical/logical replication, crash recovery, pg_dump/pg_restore, etc.
How does your thread-per-connection model compare to Heikki's proposal[0][1] from back in 2023?
[0]: https://www.postgresql.org/message-id/31cc6df9-53fe-3cd9-af5... [1]: https://www.youtube.com/watch?v=xLLakMmVtbY
- Use thread local variables
- Move everything from shared memory to process memory
- Use threads instead of processes
I've started to see meaningful benefits by changing the parallel algorithms to use a shared memory space. For example parallel hash joins have to copy tuples through shared memory to pass them between workers. That's just not something I have to do.https://learn.microsoft.com/en-us/sql/relational-databases/n...
On the client side, there is usually a local connection pool. When a burst of traffic comes in, the client needs to either wait for the pool to free up or establish a new connection, which adds latency. This latency hit wouldn’t occur with multiplexing.
With multiplexing, systems like pgbouncer would be unnecessary.
Also, even with a thread-per-connection, you can still quickly exhaust the servers resources when you have lots of connections because threads have a lot of overhead. Reducing the number of connections needed would greatly increase the number of clients that a database can serve.
This naturally lended itself to a suite of skills to describe how to rewrite a crate from unsafe rust to idiomatic rust. The main three skills I had were 1) a skill for identifying the next crates to port 2) a skill for rewriting a crate and 3) a skill for auditing a crate and making sure there weren't any outstanding issues.
My exact approach for managing subagents changed throughout the project. Initially I was doing parallel coding sessions with Conductor. After dynamic workflows came out, I used that as it was really easy to spin up dozens of parallel subagents and manage it from a single orchestrator. Over time I switched from using dynamic workflows to manually spinning up subagents from a central agent. The issue with dynamic workflows is they waterfall. Each step needs to finish before the next one starts. By manually spinning up subagents, I could have claude start porting a new crate as soon as a prior subagent finished.
The reason to use threads is almost entirely about ease of development, not about performance. If you use shrared memory like PostgreSQL does you need to write your own allocators, etc. So much you get for free if you use threads.
This is very not true. When it comes to parallel queries, a process model adds a ton of overhead. You can't pass pointers between processes because the address space is different. This adds a ton of overhead in a bunch of different places. For example when doing a parallel hash join, Postgres will have each worker build a local hash table. Then it will take all the tuples out of the local hash table and copy them through shared memory to the leader who will then construct a new hash table. This duplicates a lot of work as you have to hash the tuples multiple times.
A lot of getting to Clickhouse level performance was making better use of parallelism.
Additionally the reasons PostgreSQL does not offer Clickhouse performance has very little to do with parallelism. PostgreSQL plans to move to threading but the efforts around imporving OLAP performance are almost entirely unrelated.
That distinction is important as pointers generally cannot be shared (a problem which can of course be solved with one more indirection ;-) .
But concurrent access, so synchronization is required (lock or whatever), so overhead :)
Doesn’t that kind of prove the parent’s point though? In theory shared memory can do anything that threads can do. But if in practice some feature doesn’t get implemented in the multi-process design (because shared memory is hard), when it likely would have been implemented in a threaded design, then that’s still an advantage for threads.
Passing a pointer between threads requires going through the memory system and letting cache coherence algorithms sort out the data sharing between cores (with or without a futex lock/unlock depending on implementation). Passing a SHM offset between processes requires going through the memory system and letting cache coherence algorithms sort out the data sharing between cores (with or without a context switch to the kernel depending on implementation).
It's not that different.
MSSQL shares cached query plans between connections including jitted code, PG cannot do that and the changes needed to make the plans cross process portable would be extensive while sharing between threads is just normal code sharing between threads.
A very long time ago, there was once a feature called "Data Blades" which tanked a commercial database vendor. A badly behaving blade could bring down the entire database. Most anyone who has been working on databases for a few decades remembers this and makes a point of either not introducing these sorts of features or making use of processes over threads.
I have not looked at the code referenced in the mentioned project, but thus far I haven't seen a model that could craft a complete SQL parser on its own.
There are a number of problems, and design decisions, that a developer decides on when writing a database that I don't see any current models… just because you have the ingredients does not mean that the stew is edible.
I have no idea what this is and a web search turned up Harbor Freight woodworking tools.
And what you found seems to be "Dado", not "Data".
Then I made a second web search: data blades database.
That turned up some ibm database software module technology which I assume is what's being discussed.
It would have been less effort than it took you to write this comment. Perhaps next time that you can’t be bothered, just ignore the comment and move on to another thread that meets your required spoonfeeding levels.
Doing a few searches and reviewing their results is effort.
Google doesn't really say what went wrong if it's about Informix.
Clearly a process per connection is more stable and that's what I'm using.
It's unclear what problem such optimizations are solving anyway, with the old way you could only support a million concurrent users with a single server? Are we missing out on supporting ten million concurrent users with 2 servers instead of 10? Ostensibly reducing the minimum db hardware opex for a 10B$ company from 10k$/month to 2k$/month?
Even if those processes share most of their memory, and are written in a notoriously memory-unsafe language?
A significant performance improvement can well be the difference between being able to run the entire database on one beefy server, and having to shard. And that has a huge cost in terms of complexity and thus reliability and development time.
It does this because it can’t possibly know whether the dying process did bad things to the shared memory pool.
Built-in is also possible: just fork once after start, and you have parent as watchdog and restarter.
The extensions might need to be rewritten, but hey, we have AI for that now, so why not :-)
(Or I guess it would get stuck in a doom loop or something?)
also have you told Ben Dicken ? https://x.com/BenjDicken/status/2074326407795417435
Right now OrioleDB is in beta. Once that becomes production ready, I'll evaluate incorporating it into pgrust.
For Ben Dicken, he has seen the project: https://x.com/BenjDicken/status/2074512043462603236. We're still working on all the novel features so I don't think it meets his bar quite yet.
[0] https://www.heap.io/blog/testing-database-changes-right-way
[1] https://www.heap.io/blog/analyzing-performance-millions-sql-...
[2] https://malisper.me/table-of-contents/
Just checking, is fsync on? :) Regression tests don't catch bad IO patterns afaik.
Anyway... sounds like a fun project to work on!
If those don't exist, I hope folks recognize how useful they are and add them.
I'm playing with a POC for a better wire protocol here: https://github.com/solidcoredata/pgwire4
Everyone is so worried about the value of commodity software going to zero. It's like, yeah, going into CS for the money always looked dumb to me, it's just not a good career path for that, you have to love it.
I am way more excited about a whole new class of stuff that obliterates the state of the art at every frontier.
Keep doing it legend.
use both synthetic and real data to sample the internals of the original software to duplicate.
locate all the data transformation junctures, sample and then replicate the tranforms 1:1 in the rewrite.
Faster is quantifiable. How do you measure better?
BTW, showing no respect to what it is trying to copy looks uncomfortable.
I am simply curious what the benefits of using Rust are in this instance.
good luck nonetheless
Now, having gone through several such endeavors originally myself, albeit with internal tools and systems (as an exercise), I've noticed that while all my tests passed with flying colors the rewrite itself was broken even on basic functionality or missed a ton of details. It was in effect useless when I dived into it. Initial tests also showed massive gain in performance, and I know people who were involved aren't really dumb so something smelled funny. Turns out all those things left out and honestly... moments were the key ingredients.
What I did learn from those beginning explorations though was that one-shotting, grand architecture or source up-front, master plans up-front.. all these do not yield good results - YET. Who know what we'll see in few years though. What I did found that works (FOR ME, nota bene) is to keep the design and checklists for myself, written by myself and then do a small piece by piece.. as if you would if you were coding alone or if you would waterfalling a small team of talented juniors. Then, suddenly super happy results come out, but then it's mostly you driving all the way where llm writes code and offers advice (which for the most part you ignore). It's a happy place for myself at least. It's then truly unlocking yourself to the mythical 10x.
Rewriting a large proven system with decades of ultra expertise behind it, which I don't have, is guaranteed not to end up the same 1:1 replacement. If you found a recipe for that - please do share.
If LLMs can be utilized to quickly make deep testing possible, I think that's probably a net-positive.
In particular, if you put an LLM in an automated loop of "this test fails, please fix it", there is a pretty good chance that it will simply special case all of the tests, possibly in some contrived way that makes it not at all obvious when you read the code.
A truly stochastic method is more likely to hit against edge cases, rather than an agent that tends to towards idiomatic solutions and that is trained against a corpus of existing software, and burns millions of tokens/watts spinning its wheels.
^ There's plenty of business value to be found in agentic AI without reaching for it for every solution. I'd even posit agentic AI is even better when paired with focused old-fashioned squishy-brained software engineering in the loop.
Maybe a way of looking at it, to understand the nature of the issue. Have a LLM translate a novel from English to Spanish. Of course it can do that translation at speeds that no human could (score a point for AI). But how good is the Spanish translation? Is the quality better than what humans could do? Wouldn't those who are not fluent in Spanish be more easily impressed?
We then can do all kinds of configuration setups and tests, but how do we know the Spanish was translated perfectly, without a massive detail review (and being already truly bilingual in both English and Spanish)?
As is the usual case in the pursuit of perfection (which nothing in nature ever seems to be), there is going to be mistakes, costs (worth it?), and gray areas. It would be foolhardy for us not to suspect or pass it off as otherwise.
You can't. I think that's a large part of why LLMs have caught on much better with programmers: they have ways of making the computer check its own work.
Checking a document is still a laborious manual task. And completely unfulfilling.
> making the computer check its own work
Kind of like the Spanish teacher telling his students they can grade their own tests, then being surprised that Billy was always giving himself 100%, when he's nowhere near that bright or fluent.
It wouldn't be so bad, if people were more upfront with being unsure or made it clear they were extrapolating from smaller and limited data. But usually, like many of these unusually cocky LLMs, what is too often reported to the public is "perfection" and many inconvenient truths "swept underneath the carpet".
That's the culprit, because LLMs tend to forget and remove a lot of branch logic in these kinds of tasks. If unit tests don't cover these specific if/elseif/else cases, then they'll just disappear.
They'll also disappear if the LLM is allowed to modify the unit tests, because they sure like to cheat their way around into greenlit test suites. The agentic environment must disallow write access to the unit test files for the agent that writes the code.
If you implement that in your tools, you'll see quickly how the models will try to rewrite the unit tests at all cost, no matter what kind of prompting you've done. Tool policies are the only boundary to successfully guarantee this.
Source: Am building my own agentic environment because of that behavior
An example is Fable being released. I felt like the most complex thing I was willing to sludge through was having it clone llama-server's web UI with my own opinions (I really like the original, kudos to them). And the initial skeleton was working so well I felt like I had sunk the tokens and committed to getting it the rest of the way: https://inkcap.click
However, Postgres is a tool with clearly defined functionality and doesn't have ambiguous requirements that are seen in user facing software. As a result, it is entirely plausible that the author created a working Postgres replacement for certain use cases.
I personally want to see more evidence about the quality of the tool after it is in a finished state.
I can also do it if you would prefer...
- typically they are behind a single person. That’s usually bad because of spf
- typically they are achieved in a very short amount of time, so the author hasn’t acquired any discipline in creating the project. That means it’s unlikely the author is going to stick to the project in the mid and long term
- anyone that wants to contribute to the project needs to pay. Needs to pay tokens because it’s increasingly difficult to maintain these projects without AI
So, who wants to put something like this in production? Doesn’t make much sense
You can use llm to pull in updates as they are released. It’s not gpl, so you don’t need to publish your port
2. This project is AGPLv3.
People in AI psychosis don't know that.
And there are others doing it for projects like Armbian, openwrt, etc.
that hits your metrics without the problem that your contributions are not welcome.
It's pretty much impossible in a project of this size. IIRC Postgres has over 1M loc.
I likely wouldn't use a rewrite of such a huge project if it doesn't have the backing of the original team (or a significant fraction thereof) and a believable story for having matched/exceeded the original code quality and maintenance. I also think in general using an LLM for license-laundering is legally and morally hard to defend, although this case is different in that they chose a more restrictive license. Not a lawyer, but my understanding is that you can just download PostgreSQL, do s/MIT/AGPL/ and release it, legally. (The original MIT-licensed version still exists, so no reason anyone would prefer yours until you make another release with some compelling new feature.)
Nobody else would either.
If this is meant for personal learning, do it that way and make it clear that others should not even consider using this project.
In fact, even for personal learning it's wasteful. You can learn so much about database without a rewrite like this.
Finding exploits is getting exponentially cheaper, and the cost of producing proofs is rapidly going down. For a lot of software correctness is rapidly becoming non-optional.
People with no experience don't have enough experience to realize what exactly they are missing here.
Exactly. And this is why those projects are typically called "XXX in Rust" or "XXX-rs". Because the creators get to do their favorite thing - coding in their loved language - while skipping all the hardships of designing, accepting real feedback, involving users and getting traction - all while simultaneously hijacking the existing brand.
As of now I know of a single project that changed their name after being called and the project surprisingly got some traction.
Lindy effect! The longer something has been around, the longer it probably will be.
"Status:
pgrust is not production-ready yet. It is not performance optimized yet."
The maintainer is not suggesting you use this for anything yourself. So why do you care about spf or (lol) his "discipline in creating the project"?
Nobody is saying this author hasn't demonstrated discipline & won't maintain this project, but the statistical averages across most projects fitting this trend make it likely enough to question their worth in aggregate.
People on HN love complaining at any given moment.
I’d wager most of these people don’t really produce much and are constantly bikeshedding.
(Repost of <https://news.ycombinator.com/item?id=45253509>)
In five? Everybody but me.
I don't think anyone suggested deploying this to production - the author is quite explicit that it's an experiment.
And maybe Remacs will get reactivated https://github.com/remacs/remacs/wiki/Progress
Maybe even I'll be able to do it when I wait for the bus!
One of the things I'd typically do is peek at the commit history. Seeing what people worked on and how they did it tends to say a lot about a project. But with LLMs generating 7101 commits in less than a month that isn't feasible. Even looking at a single day is way too much [1]. It probably also doesn't make sense since the commits content won't tell you much anyway.
ps. How do you easily get to the first commit in a repo on GitHub? Browsing commit history feels rather tedious
[1] - https://github.com/malisper/pgrust/commits/main/?since=2026-...
These rewrites are just test-driven development taken to the absolute extreme. Created under the hope that the existing tests are exhaustive and cover every relevant use case, such that if they all pass, the rewrite must be at least as good as the original. So just go with the vibes and burn tokens until they pass, and your job is done.
In practice, this is never true for any codebase above a certain level of complexity, especially not one as mature and widely used as Postgres. But reality doesn't seem to be an obstacle for vibe coders.
If you find some, fix them.
Went straight into my vault of brilliant quotes!
If ya don’t wanna use it, don’t. Simple.
In the world of exclusively human written software the existence of the artefact itself (code, documentation) served as the proof that there’s someone with half a brain behind it. Now that’s not the case anymore.
The conclusion stays though - it’s OSS, authors/maintainers have no obligation to anyone to do anything. Like it, use it, don’t like it, don’t use it.
As for me, I’ve found that the community and activity proxies are still good.
Definitely still something to look into. A project I'm checking in on from time to time is https://github.com/emdash-cms/emdash/.
It will be interesting to see how the project activity is unfolds? Are people using it in production. How many errors do they find. What do those fixes entail. What happens with the docs over time. Etc.
I haven't had a change to look in depth, but based on a quick glance I'd say that the activity on the project seems like the tempo you'd expect of a similar open source project.
Why is that a challenge? As long as they are open about this, all is OK.
It was also never meant to hit production.
https://cli.github.com/manual/gh_search_commits
here's the docs with more syntax using the "before x date"
https://docs.github.com/en/search-github/searching-on-github...
there's also an advanced search page, but it does not support commits when filtering with dates
https://github.com/search/advanced
or you can bisect the date in the search widget, this is the first day with a commit
https://github.com/malisper/pgrust/commits/main/?since=2026-...
first commit:
https://github.com/malisper/pgrust/commit/22113dc36b02973060...
Maybe I'm just being a little grumpy. If I really need to look into a repository, I clone it and use vanilla git command line tools to have a look.
It's just annoying that the modern web UI from GitHub takes >1s second to load a page with 34 commits
That's a wrong question. The right question is "why would one go about rewriting a piece of code in X". Once and if you find a good answer to that question, you will see the answer to your's.
You can use the syntax github.com/user/repo/commits/?after=last_commit_hash+number_of_commits-2 (-1 for the latest and -1 for the last)
ex : https://github.com/malisper/pgrust/commits/?after=3646a73515...
I think the focus for projects like this is going to shift to reviewing the testing/fuzzing process instead of reviewing each commit (going much further than what the postgres regression/isolation/crash tests do).
related post from danluu: https://danluu.com/ai-coding/
Manager: You’re doing amazing work — zero bugs in production! I’d like you to mentor the other SWEs on how to get their bug count down too.
Engineer: We’re allowed to have bugs?
Hardware Engineers: "None. We'll fix it in firmware."
Firmware Engineers: "None. We'll fix it in software."
Software Engineers: "None. We'll document it in the manual."
Technical Writers: "None. The user can figure it out." etc.
Me: This is what you said it does, and this is what it actually seems to do. Which one is right?
Engineer: Shit.
Also helps if you fix the bug or change the behavior, the docs are still technically correct. I'm only partially kidding, I swear I've seen this a million times in documentation I read.
Sadly, monospaced fonts kill sarcasm.
If you first carefully define the overall architecture and thus individual high level components of the system, then you know which of those components are mission critical and which are commodity. Mission critical would be anything ensuring ACID, etc. That way, no matter what you farm out to LLMs, you can keep the majority of limited human focus on the far fewer mission critical components. If tests end up not being robust enough to catch all issues, at least they'll be isolated to commodity code where damage is limited to things like DoS, etc, and not code that could cause data loss.
I also think it's important to first define the _contracts_ on and between each of these components, and derive tests from those contracts. Partly because contracts more succinct and easier to reason about. And partly because Rust provides many tools to enforce contracts at compile time, reducing the need for tests (which themselves could end up subtly flawed). Contracts can be enforced through typing, private vs public APIs, etc. Newtypes are _incredibly_ powerful for both enforcing contracts and making footguns much less likely.
I've got insanely good at designing testing oracles over the last year for exactly this reason.
I've ported some extremely finicky software between languages that it would have been borderline abusive to have a human do.
Codex 5.3 and later for those interested.
https://news.ycombinator.com/item?id=48856535
Though beyond testing, I think there will be increasing focus on proofs of correctness. (Testing can only show the presence of bugs, not the absence. —Dijkstra)
At any rate, it's never been this cheap to produce the proof of correctness of a program, or on the other hand, to produce an exploit for an incorrect program.
I usually check the history of a file not easily changed like .gitignore.
The first commit seems to be this one
https://github.com/malisper/pgrust/commit/22113dc36b02973060...
On the other hand, aside from the commit messages, one didn’t ever have access to the underlying thought process of human developers either, so maybe it’s not equivalent to say that secret prompts mean closed-source.
> The "source code" for a work means the preferred form of the work for making modifications to it.
With that definition, there's definitely space for arguing that the AI tooling for modifying the code is necessary for the modification process to be sane therefore "preferable" for any human, if the code is "designed" (or lack of design thereof) around the idea of being AI-maintained.
Otherwise, it's not source-code, it's not meaningfully-modifiable, it's basically equivalent to just decompiling a binary. (similarly-bad quality may of course be human-produced too, though then at least you have direct proof of it being the preferred form for at least one person - the author)
Then I lost count, so I ran wc -l Cargo.lock
1467 Cargo.lock
Easily over a thousand dependencies. And "rewritten in Rust" is supposed to be a good thing? I bet this doesn't even compile faster than the original.The lock format is a multi-line TOML, with a varying number of lines per dep due to redundantly listing deps-of-deps, so a naive line count massively overstates the number.
Cargo.lock contains many unused dependencies, because it's a superset of all combinations of all optional/disabled features of all transitive deps across all possible platforms (so that the deps don't reshuffle even if you enable/disable feature flags or compile on another platform). But that means Cargo.lock is going to have 3 async runtimes even if you use one. It's going to have syscall definitions for RedoxOS and wrappers for WASM, because some dep of dep is compatible with those platforms. But these deps won't even be downloaded if you don't build for these platforms.
The number you got presented is not representing the unit you're insinuating. A crate in Rust is a compilation unit. It's common for projects to ship as a collection of many crates. It's a smaller unit than what C counts as one dependency, and slightly coarser than an .o file. I don't see people freaking out by how many .o files their projects have, including all transitive ones from deps like openssl or curl.
I could not care less about any of this. Truth is code, as it is now. I don't care when (and certainly not by who) a bug got introduced, it's here, shut up and fix it.
don't be obtuse. Nobody needs to do either.
> But with LLMs generating 7101 commits in less than a month that isn't feasible.
I don't think trying to understand LLM generated code is feasible for anything other than very small projects. IMO it's a big problem with using LLMs for coding. Sure, they can generate a bunch of stuff, but in some ways that just makes the real problems of software development even harder.
If there's particular unsafes that you think are egregious, let me know.
a few hours later
Fixed!
The difference with a Rust codebase like this is that all of the unsafe code has been neatly isolated and clearly marked. The outside code is safe — at least according to the definition of what Rust considers safe, which is a high bar indeed and objectively superior to the unsafe mess that is C — and the unsafe code is naturally fenced in, which means that it can be seen by developers and tackled by incrementally.
In some cases unsafe is unavoidable, but it is possible for a human to verify that it is, in fact, acceptably safe even if inside an unsafe block.
I like the AGPL and think it's the best truly free open source license, but I worry if this is compatible. Ie, if this is rewritten from the original source, should the original apply? (Yes.) There has been a trend to rewrite open source software with a more restrictive license (like coretools in Rust). This looks considerably more ethical by choosing the AGPL - I just wonder, safer with no change at all?
[0] https://www.postgresql.org/about/licence/
[1] https://github.com/malisper/pgrust?tab=AGPL-3.0-1-ov-file
And it doesn't violate the PostgreSQL license to license the rewrite more restrictively. That's part of what makes MIT-style licenses less restrictive than the GPL or AGPL: they allow for more-restrictive relicensing.
I’m still putting together my thoughts on various open source licenses especially as we see automated AI rewriting.
That's what LLM companies have done for years anyway. Inline completions are trained on licensed code. And nobody cares! ;)
I agree, which is why I license my work under copyleft licenses such as AGPLv3 so that anyone has to make their modifications public too.
I think LLMs (especially closed-source models) will make this worse.
I wonder what communal answer you have for someone who would say, "moi2388, your work will be now done by moi2389. Thanks and good bye."
hear hear, and good riddance too.
The thing you have to be wary of with movies is trademark law. Your Star Wars copy can't use the word "Darth Vader", that's trademarked. It can't use Darth Vader's mask, Darth Vader's suit or Darth Vader's breathing either, all trademarked. And with trademark law the bar to pass is basically "would a reasonable but uninformed consumer be at risk of confusing your product for the trademark". LLMs can't launder that for you. You have to make actual changes, like Spaceballs did
Comprehend it this way: You create a blank (A)GPL project and incorporate the upstream BSD codebase into it. While those original upstream files remain under their original permissive license, the project as a whole is governed by the (A)GPL (plus the attribution requirements of the upstream license, which the GPL permits). From there, you can add your own code under the AGPL and distribute the combined work under the AGPL.
If someone takes your code and uses only your portion, they can use it under the AGPL alone. However, if they also include the upstream source code, then the attribution requirements of the upstream license must still be met.
If it is not a derivative work, then for copyright to apply at all then it must be an "original work" which has "at least a modicum" of creativity applied by malisper in the translation. If this is satisfied then malisper could choose any license for the translated code they want, compatible with Postgres or not. If it isn't satisfied then no license applies, because it isn't eligible for copyright - essentially it is public domain.
The safe and polite thing to do is to keep the same license when performing machine translation.
This practice is entirely compatible with the PostgreSQL License, but it is often prohibited by GPL variants. You typically cannot combine GPL code with code under most other copyleft licenses, such as the Eclipse Public License.
Regarding copyright status, AI-assisted work is increasingly recognized as copyrightable in many jurisdictions, provided the process involves a sufficient level of human creative input (though the specific threshold varies by jurisdiction). Only work generated purely by AI, with no human involvement, is arguably public domain. In a case like this, which is akin to "pair programming," the output is almost certainly copyrightable.
The BSD license only explicitly permits the author “to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement.”
By default, the owner of a protected work retains all rights not conveyed to someone else. Changing the license isn’t one of the enumerated activities, and so I think there’s a case to be made that it’s not permitted.
Now if the author wants to claim it’s a new work, as opposed to a modification (which opens up a big bag of issues by itself because this was AI-authored), then the author can license it however they see fit.
A bit like me buying a comic book, then offering to sell it to you under the condition that you never let my brother read it and that you make any future owner agree to the same terms. That's perfectly legal, and there is no reason I would need permission from the author (or publisher) to do that
Suppose you get a license to view a copy of a work (streaming or a paid subscription to a newspaper site). Your permission to consume the media begins and ends with the license terms, which allow you to view the work (and, since it’s necessary, to make a transient copy) during the period of the subscription. You don’t get to relicense it to someone else under those terms.
For instance, if I take a copy of $BIG_BUDGET_MOVIE, and resample the video frames from 1080p to 720p through a purely mechanical transformation, that doesn't make the output public domain.
The BSD license doesn’t explicitly convey the right to create derivative works but it does convey the right to “modify” the software. (They seem similar but “modify” is a narrower verb.) So is this a modification? A derivative work? A new work entirely? If it shares no code with the work from which it was derived, things are more complex than it may seem (and it no longer fits the “compressed video” analogy very well).
Surely you wouldn’t say a Spanish translation of a Harry Potter work is in the public domain while the original work is under copyright?
I imagine a court would call it a derivative work if tested.
The licenses tend to say unmodified or modified copies can be redistributed in source or binary form “provided that the following conditions are met”. Relicensing the code in a way that guarantees those conditions are met has been the accepted thing to do in the community for years - whether that’s GPL/LGPL/AGPL or a proprietary license.
As you said, the question has never been litigated or settled.
I wouldn't go as far as calling permissive licensing "restrictive" because they actually allow for reducing freedoms; but copyleft is definitely not restrictive at all, it's the opposite.
Having said that, I like and appreciate both kind of licenses and I have and will continue creating open source software using ones or the others.
Such crude takes only cause unnecessary friction. If you have a black box that spits out code, and you are unable to distinguish the quality between a top tier dev and an AI inside the black box, then the distinction is unnecessary. Most of the code on the internet is already a black box to you. What percentage of code running on your machines have you vetted by who wrote it and code quality?
AI coding isn't going anywhere and will likely end up generating most code going forward so instead of rejecting it outright or arbitrarily categorizing it we need to focus on solid quantitative and qualitative measures of code and functionality regardless of who wrote it.
However, Jarred still describes a lot of unsafe, and usage of Miri in continuous integration.
Funnily enough, RAII is cited as a major benefit of rewriting from Zig to Rust, while C++ already has RAII. I wonder if C++ and Rust are more suited to larger programs than Zig, unless the architecture in Zig is handled carefully.
Also, the unsafe footprint seems reasonable — the bulk of it in FFI wrappers.
If the dev doesn't vet the code, it doesn't matter how good quality a dev they would be if they wrote the code - they didn't. Sure, the dev would probably drive the initial architecture discussion better and some people are using AI in small batches with tests and vetting everything, but some previously great devs are throwing in PRs that touch hundreds of files at once with one commit.
A lot of people I previously considered great developers have become people I would not recommend for a job in the past 2-3 years.
> If you have a black box that spits out code, and you are unable to distinguish the quality between a top tier dev and an AI inside the black box, then the distinction is unnecessary.
Sure, but this is just begging the question. If nobody could tell, the term 'slop' wouldn't have become so popular.
100% there is slop created by humans and really solid code bases generated by AI driven by a meticulous developer. You are making the exact error I was addressing, which is bucketing all AI code as the same.
> I never claimed that there wasn't AI slop
No, but you implied that a top tier dev doesn't produce slop when using AI.
> If you have a black box that spits out code, and you are unable to distinguish the quality between a top tier dev and an AI inside the black box
My point was that "if" is doing a lot of heavy lifting here and you're coming very close to begging the question.
> bucketing all AI code as the same.
Most people are not "top tier devs" and over time this will probably become more true. Even if I accepted your premise that "top tier devs" only generate solid code bases with AI, the ease of entry and the ease of spitting out thousands of lines of code means the ratio of bad AI to good AI will not go in a good direction unless it becomes too expensive for non "top tier devs" to use. Given this, I think it's fair to assume AI code is low quality until proven otherwise.
I also did not claim that all "top tier devs" would always produce better code with AI, but the qualification for a "top tier dev" in this case would be someone who verifies code multiple ways to make sure it is correct. I've seen amazing code come from bad interns that was reviewed mercilessly by season devs, and there's absolutely no reason it would not be the same with AI generated code.
You do realize that you can review the entire architecture and code line for line even if it's AI generated right? My black box comment did not mean you couldn't see the code, it meant you don't know whether a machine wrote it or not.
When I read things like this it makes it very hard to give any credence to the rest of your pro-AI arguments, because it just seems incredibly likely that you're a bullshitter.
BTW, I'm not alone in my opinion on AI:
https://www.reddit.com/r/LocalLLaMA/comments/1uxbrw4/linus_t...
Aren't you making a strawman argument ? AFAIK this project is not made by an official PostgreSQL core developer, so the entire premise of your argument is invalid.
So how much AI usage does it make it an “AI rewrite”?
Who wants to contribute to an unmaintainable code base?
Once the free money dries up that number will rapidly tend towards 0%.
> So how much AI usage does it make it an “AI rewrite”?
Any amount.
Except for when they do, like the new TypeScript...
It was trained on all code the code that could be found.
Not just code written by genius programmers like Carmack and Bellard.
Given that it's average, I'd prefer a human coder above average :)
I've been programming a long time and considered myself among the top in my domain and AI agents using like GPT 5.5 etc. are much better than me.
Ex falso quodlibet
> I've been programming a long time and considered myself among the top in my domain
I am not trying to attack you, but you considered yourself that... I don't know whether you actually were and frankly I don't care.
Then, by giving them context or by post-training, you can make them sample non-average parts of the distribution they learned.
How do you derive that something is "below average" or "average" or "above average"?
In the case of real world LLMs and post-training, what is above average is defined roughly as: labeled good by expert humans, and scoring high on RL environments related to coding like debugging, passing tests, or running efficiently and verifiably correctly.
One technique is RLHF: have an human expert assess it.
Like a short example is easier to grade, but not in the same ballpark as a whole codebase.
How do you? I mean, that was your point basis.
It’s mostly grunt work and LLMs are well suited for translation tasks (iirc transformers arch was originally invented for translation)
LLMs sometimes confidently leave things out or they will overbuild.
I use them all the time but mistakes happen. It's not exactly a scalpel, more like a sledge hammer.
is it the craftsmanship, or the deliberate decision making of industry veterans?
Hours of human attention
or a few seconds of AI attention?
I am not just talking about writing the code but the brainstorming that goes into it.
`mostly` is doing a lot lifting here. The Go rewrite uses plenty of copilot. The reason you trust it is because you trust the people doing the rewrite.
So no, I wouldn't judge a rewrite as being equal just because it passes the tests. That said, I don't think that means you shouldn't do it. You just have to be pragmatic about it.
This is not true, even in principle, even for Postgres itself. You'd be right to say that it'd be hard to pass the test suite and not be robust at all to some extent. But even in Postgres, I bet that you can quite easily introduce a change that will pass the whole test suite but reduce robustness compared to the latest release (for a somewhat silly example, add a call to `exit()` on a timer that's longer than the longest duration test in the suite - that will significantly reduce robustness while still passing the entire test suite).
I'm not at ease regarding LLM generated code changes to a project with a (hopefully) long expected life time, but LLM generated regression tests should be less contentious. I wouldn't expect them to be maintained much; rather, if they don't perform as intended against a future build, just have them recreated.
"Program testing can be used to show the presence of bugs, but never to show their absence!"
Even a 100% test coversge is far away from verifying all behaviour.
Every bug report, code change as a result, PR / commit message, PR comment that steers preferences, etc. is solid signal to generate future tests.
Most extensive test suites are exactly production scars: every time you have a bug or a regression, you write a test that confirms correct behaviour.
SQLite is a good example to bring up because its extensive closed-source tests are what’s often cited as being what keeps people from forking it. (Turso did it, though, but it takes a company to deliver some guarantee of equivalent diligence.)
And yes, years and years of running.
I think this is also where the real work is. A rewrite is one thing, that you can show off with a flashy blogpost. The maintenance, for years to come, won't be of that nature yet it still requires as much work.
They aren't the bugs you get when you write it in Rust.
The kind of bugs you get are usually a function of the problem, language, implementation approach.
But, there are also levels, in terms of quality and human code review, when dealing with rewrites. New bugs can be introduced or there can be style issues, that can take time to fully reveal themselves, and particularly if the person or people involved are not familiar with the other language.
Getting an extensive test suite passing is certainly orders of magnitude better than having no test suite at all, but it still doesn't tell you as much as you need to know. I would absolutely never trust an LLM Postgres rewrite (in any language) in production based on "only" Postgres's test suite passing.
This space of things is astronomically larger than the space of things expressly covered by any test suite.
"Program testing can be used to show the presence of bugs, but never to show their absence." -Edsger W. Dijkstra
Fable's napkin estimate of the effort required to produce a passable reference semantics for Postgres, which would involve novel discoveries in denotational semantics of concurrent transactions and so on, might be in the ballpark of 30–60 years of PhD level work.
So realistically I think the only way to validate a Postgres implementation involves differential testing, fuzzing, acceptance test suites, etc. And still you'll have bugs that need to be hammered out the good old fashioned way.
There are reasonable arguments against language ports, but this is not one. You're making an argument against code changing at all ever.
If you can be 100% guaranteed that there indeed is a test for every occurred bug. Sometimes maintainers are not so strict about it.
And some programmers are so good that some issues are self-explanatory and they write good code to note a thing but don't write a test, because implementing the test is more expensive.
You don't write a test (just) to verify that your change fixed the issue, but to ensure it doesn't regress in the future after an unrelated refactor.
While not an exact fit of an analogy, those tests patch what was a problem with Postgres in the wild. What it doesn't cover are the things that worked in Postgres without tests, but may fail in port and go undetected.
1. Every test that is written is another use case that wasn't tested before. 100% test coverage is often impractical, but the more tests you have the more of the code you can be confident about.
2. Every test you add is another regression that can't happen in the future; if you test the index rebuilding code and validate the output then you know that you aren't going to make a change that breaks the index rebuilding code. If you have a legitimate change you update the tests, but if you're not expecting the change then you know there's a bug somewhere.
> every time you have a bug or a regression, you write a test that confirms correct behaviour.
What I fail to see in these rewrites however is - what about new bugs introduced by virtue of this rewrite? I mean it'll have to go through its own challenges in real-world scenarios, right?
The biggest lie of software engineering is that everything can be testable with tests. That a 100% test coverage is an indicator of quality software.
Software like a Database should have an extensive test bench with concurrency tests, all corner cases etc.
I'm not here running the new version on production to tell the maintainer/devs that my 'production unit tests failed'.
What is this even for logic?
I mean there is balance when i write tests for my production software, but my software is used by me. If i would have a library, i would test everything.
And there was some blog post about another database system were they even virtualized the File access to test cases like when the disk controller stops working.
The problem however is non-covered success cases. A visualisation of the problem: let's say universe of interaction for DB consists of 10.000 SQL queries. Over 10 years various regressions were found and 2.000 SQL queries are guarded by tests. In reference implementation remaining 8.000 never surfaced over this time and it's unclear if they will work.
And, thinking of how many various SQL queries PostgreSQL users around the world are using vs the test cases covered it's obvious that feature space isn't covered in 1% of the success ratio cases.
Now the new, test-based implementation, has to prove it can handle remaining 99%.
There's another way to validate the rewrite though. Just run both pgrust and postgres and compare the output. Know of an edge case? Run it too. Doesn't know? Use a fuzzer or some automated tool to find interesting inputs. Found an inconsistency? The input/output pair becomes a test case now
Not sure if there's tooling for that though. If there is, just give it to Claude so they will incorporate it in their development loop
I can recommend proptest. What you're describing is a common pattern in property-based testing which basically boils down to "comparing against an oracle". In this case, postgres would be the oracle, pgrust is the system under test, and the idea is to generate strategies comprised of sequences of valid (and invalid) SQL statements and ensure the system under test behaves the same as the oracle in every case.
The space of inputs and outputs is infinite. You can't prove programs are the same by "just" testing a bunch inputs.
Neither postgres nor pgrust have their behavior specified using formal methods. (pgrust could write some contracts using something like kani or creusot, but having upstream postgres also write contracts is a tougher sell). If they had, one could write a giant proof that said the two software essentially do the same thing (at least in a subset of environments and some simplifying assumptions)
If a Rust rewrite of any of your software becomes available and you aren't installing it immediately and without reservation, then you are simply not giving security the priority it both demands and deserves, and that makes you disastrously insecure. This is a serious issue that should be given all priority. There is no room for debate. Your only policies should be security before all else and compliance with those policies must be absolute and without deviation, or all is lost.
This is silly.
Rust is awesome, and it's hard to argue against in many domains. However, software is more than the language it is written in or the runtime serving it. Is the Rust rewrite fully compatible? Is it supported by a strong community? Is it likely to continue to be supported? Is its release cadence sensible? Is its licence compatible with your intended usage?
There are many questions needing to be answered before making rash decisions based purely on tech.
Security is always about tradeoffs.
Con: The database no longer exists.
Also, there is more to security than memory errors. SQL injection, authentication, and access rules matter. It doesn’t matter if Rust database is secure to bad data if it lets anyone in to do anything. Or if it is crashing all the time or corrupting your data.
I think it is completely reasonable to use a preexisting unmodified test suite to state that something is working. The larger the project the more true this becomes. Real world production scars are documented and guarded against in the test suite otherwise those lessons get lost.
Also SQLite is legendary for its massive test suite and extensive fuzzing. They have 590x the amount of test code and scripts than normal code. Source: https://sqlite.org/testing.html
I was trying to call out that SQLite often credits their massive test suite for their stability but likely didn’t communicate that well.
"Mom, can I have battle-tested, reliable software"
"We have battle-tested, reliable software at home"
Battle-tested, reliable software at home: (Pic of green text from `cargo test`)
So, we should make it easier to feed that reliability back upstream.
Probably the most useful thing you can do with these LLM-transpilations for now: If the transpiled version passes all original tests, I can run my application test suite against it and use it to discover test coverage deficiencies in the original!
If it crashes or otherwise observably misbehaves, I know the real project was missing regression tests for something. We could make upstream so much more resilient against accidentally breaking stuff in future updates, if only it becomes safe (offline + no side effects) and easy (if it crashes/locks, it is not from some memory safety bug from 25k transactions earlier) to run these transpiled projects as one row in our everyday integration matrix.
I don't know why anyone would choose this over the actively (community) maintained proper Postgres project.
But I choose not to publish it or promote it for many of the reasons you mention above (and more)
... For one, if "I" can do it, so can a hundred other people. And all the bold claims behind it would need to be backed up and supported and it promoted, etc, which is a whole pile of time that doesn't involve writing code.
It's the organization around a project that matters, not the code. It's not the 90s anymore w/ people piling into MySQL because it was the only option. People aren't going to be trusting your software with their data, if they can't trust you.
And unless someone is going to dump a pile of money or something on [me|them], I don't have the ability to build that organization ... as I need to feed my family... Nor am I willing to put my personal reputation on the line by putting up a huge quickly written application and then someone finding something in it I can't explain.
So like probably 500 other projects I have it sitting in a private repo.
It's a very weird time right now. "Technical" excellence isn't the important part. Organizational excellence is. This was always the case but it's more so now.
... In the meantime, if anybody has angel investment to burn, I have something potentially better/more-exciting than this guy's project but... see above...
He has provided benchmark results which provide a dimension amongst which to measure your rewrite. If you can do better by all means post your rewrite.
Finally, these kind of projects can eventually over time become projects that are actively used. Postgres is not some entity that existed before the universe was created; it was also created by someone and then eventually adoption picked up over time.
It has a 40ish year continuous history. (Which is also why it has technical/design warts like process-per-connection that we probably wouldn't do in 2026, but that's another story.)
Even with that I remember getting funny looks 20-ish years ago when I would advocate for using it instead of MySQL.
With databases, reputation is everything.
Translations are a lot more likely to be error-free and robust, as the original data structures and algorithms have been battle tested.
The project is not cool. This is not a new idea, and there is nothing special.
Students won't use it as an example of porting code. I am not aware "porting code" is part of standard software engineering or computer science curriculum. That's not the kind of thing being taught in schools.
Companies won't switch to it unless their CTOs are either insane or incompetent.
I published similar project here: www.emuko.dev - emulator for RISC-V. This one turned out to be 3x as slow as QEMU for example.
re: CTOs - if the improvement is 3% nobody of course will look at it. If the improvement is 30%, it'll be too big for big players to ignore, so as a CTO you'll be tasked with trying it out. It's really a matter of whether this thing is safe and secure, losing data or has a trojan. If the authors can prove it's all valid working code etc., it'll be a viable project.
Sorry, as someone who has been involved in many of these decisions, I don't think you understand how any of this actually works in the real world.
It's also worth noting, that while you are able to use LLM's to produce your own translation, he's actually done it. There's value in actually putting in the work.
This isn't a unique situation at all. Many Postgres extensions are developed and maintained by a single person, and may therefore be avoided by more conservative users, even if they offer some technical advantages. To each, their own.
Everyone is standing on the shoulders of those which came before. If LLMs allow us to combine the incredible decades of effort and knowledge and experiences that's gone into building something as great as Postgres, and take that and combine the experience and philosophy that has led to the creation of a language that potentially provides tangible benefits, and for far less human time and effort that it would have otherwise taken...surely something that should be celebrated as absolutely incredible?
LLM companies steal the original work and LLM users dont even know where the replicated code was lifted from or how it was licensed.
https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...
https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...
I have taken a closer look at the code, and it seems superficially a somewhat faithful rewrite, not quite idiomatic Rust, but closer than I anticipated at first. I know there are non-LLM rewriting tools for C to Rust, and with a test suite to help, a rewrite to Rust might be greatly helped. The new Rust code does have some drawbacks in some ways, and there are topics I am curious about.
https://github.com/postgres/postgres/blob/2e6578292a9184dcaa...
That's understandable but it's still a bit of a negative emotion that probably isn't very productive. Or very rational. This thread is full of people trying to argue that this can't be any good, shouldn't be any good, and is clearly going to end in tears. And obviously this thing passing tens of thousands of carefully curated tests that accumulated over decades suggests otherwise. It's hard to argue against that.
This probably is going to have some new issues. But it's an impressive achievement.
The only one using feelings rather than reason here is you.
1. Piggybacking established brand names (Postgres + Rust)
2. … without practicality nor advancement (e.g. this solves no extra problems)
3. … without trust (i.e. LLM-driven rewrite, with no capabilities to thoroughly review it)
I think people get easily upset when the title has high-signal names like Postgres, and the title touts it somehow, yet it’s obviously impractical for obvious reasons (short-/long-term practicality, social trust & network effect, etc)
But then its credibility would be abysmally low, which makes it undesirable for the authors.
There are new power tools for our craft. People are experimenting and having fun with said power tools, and have interesting results that may be transferrable to $YOUR_PROJECT.
Doing things just because we can is a great reason for hacking around.
Kudos for the author for answering questions and keeping up resilience - HN crowd is not what it used to be (shakes fist at a different cloud).
I'd love to be proven wrong, but chances are that nobody will use this in production, people will completely forget about the project in 6 months, and the project will be archived not long after that.
This is not the first one of similar projects.
On one hand, they give an LLM a short feedback loop to correct itself, and iterate fast when writing code. A human also uses it as a feedback loop, but we don't iterate as fast and don't handle big walls of conditions, so its effect is not as big.
On the other hand, LLM's ability to handle a big wall of if-conditions can backfire if it starts taking shortcuts and taking the tests-as-a-spec too literally, overfitting the solution, overly focusing on the given datapoints (conditions checked by tests) and missing the overall behavior shape that the tests intend to pin down. For humans, this is less of a concern because we are bad at big walls of if-conditions, and we'd rather try to see the original shape that the tests are pinning down than monkey-patch the solution to fit the individual points.
It's interesting to see how one balanced these two. In this case particularly. Maybe you could play around with separating the data you give an LLM into "training set" and "validation set", training set can be seen fully, but validation set is hidden and is only queried when the solution is deemed ready. Say, training set = original source code + half of the tests; LLM uses that for quick feedback loop. And validation set = the remaining half of the tests; test code is not shown to the LLM and run only when the LLM says it's done to catch potential overfitting of the resulting solution over training set.
To me, the credibility of a solution like that would depend on what methodology the authors used. If they just let the LLM see all tests, I'd be skeptical (albeit unable to point out specific bugs due to the volume of work and LLM's ability to make bad things look trustworthy). The good thing is, real-life use will add new, unseen before datapoints for testing — so validation set will build up with time. Really curious to see how it will work.
I'd like to know if the "authors" know what I'm talking about.
We really should have used postgres instead, but it was the "big data" period so you had to use mongodb.
Aiming for postgres compatible database with a 2026 architecture
[0] https://malisper.me/the-four-horsemen-behind-thousands-of-po...
Except you didn't improve the architecture, did you? You just asked an LLM to copy what was already there. Making real improvements to the database architecture requires understanding the database architecture, not just asking a calculator to do the work for you.
Better benchmark performance means nothing if the underlying guarantees break, and a 300x improvement sure makes me suspicious. I would look at something like this if it passes a Jepsen test, otherwise you simply will not be able to convince me that it's worth my time.
You can say "we want it in Rust" and leave it there - I'd be fine with it. Wouldn't use it though.
Why does there need to be a business case? They aren't selling it.
I'm on the rewrite it in rust bandwagon, but I secretly want to rewrite things in rust so they can be refactored and made easier to maintain and add features. So "rewrite it in rust" is just like "rewriting it in anything that I'm currently enamored with," and doing it with an LLM (defactoring?) would miss the point for me.
rust being safe(r) just makes the rewrite less risky.
So what's the point?
but yes the test files should be presented under their original licence.
These are toy projects with no serious interest in maintaining the port long term. and even with things like bun where the port is merged it remains to be seen on maintainability over time.
source?
All these "rewritten in rust" projects only reinforce the idea that a significant part of the rust community consists of software talibans and not of engineers who must deliver something that works and is reliable over time.
You're right to talk about the trend though, because what it shows is how the cost of re-writing well covered project has completely crashed, so that in itself is a learning.
But most of my issues were related to concurrency and data sanification, especially when the other end of communication fails with unexpected behavior. These bugs are nastier than memory.
So, I have pointers, and I am not afraid to use them.
I will note that, very funny
Is managing memory safely important? YES
Is managing memory safely the solution to most of the problems? Absolutely not.
Advocating the language ignoring everything else (having as first and only argument that the code was rewritten in rust fully qualify for this case) is dogma and not engineering.
We have a problem with software religious fundamentalists in our organisation and it's an apt description.
We went down the earlier Udi Dahan and DDD crap.
Cue some story here on a bank or airline somewhere still relying on cobol backend servers.
These LLM conversions really seem to make modernization of large parts software layers possible!
There's existing money and expertise in those environments to rewrite the whole thing, yet they don't. You may loan them free engineers/experts and they might still not rewrite anything.
The existing system works. Yes, it costs a lot to maintain, and you could definitely reduce that if you moved to a more modern system. So now you're talking payback periods. Cost of development / maintenance cost savings per year = number of years before you pay back the project.
Problem is, that the cost of the development is often unclear, and the maintenance cost savings, while definitely above zero, and often unclear, and approximated the numbers usually come to a payback period in decades.
And that's without the usual tech caveats; We can't promise there won't be bugs. We can't promise deadlines will be met. We can't promise the project will succeed at all. We can't promise existing functionality will be faithfully reproduced in the new system. The normal risks around any software dev project.
All in all, it looks really expensive and really risky compared to just doing nothing and running the same old system for another five years.
Source: I helped do some of the maths on this for a Y2K project.
In 2026, not sure if it was satire. Do some people truly believe that all their software stack has to be single tech, from device drivers to end user apps? Does that extend to remotely accessed services?
I wonder if no one really thought there about rewrite that will still connect with all old dependencies with old protocols, but also will expose new kind of API that can be used by next rewritten block.
We also had mainframe, we used Oracle. It turned out that casual server is also reliable in long term and we restarted them only for upgrades of OS. Of course moving to some distributed, fault tolerant option also feels like good direction, but instead not-doing the perfect rewrite at once you can do it two/three step migration. Costs nowadays? You already fixed that.
Consider: You have a big mainframe running your tier 1 bank. Assume that you can see all the code on it, and you can feed all that to an LLM if you like. Getting it to spit out a Rust version is not what you actually want - you now have a modern language but it's still a singleton instance, so where do you run it? Most hardware doesn't give you enough uptime for what you need here, because what you actually needed was a re-architecture for distribution / failover / whatever, and while you could ask your LLM to do that you aren't going to run your bank on the result.
Why not?
I feel like we're entering a new era of prejudice against not a category of humans, but against non-human intelligences.
The design patterns for distributed and fault-tolerant systems are well-known and established in the industry. Both humans and AIs are familiar with them!
So if you sketch a design for the AI to follow, establish the rules in AGENTS.md, have a robust test suite, use a frontier model dialed up to eleven, etc... why not rely on the LLM output?
At the end of the day, humans are not without fault either.
I've been wading through some legacy "pre-AI" code recently and it has more bugs than a rainforest! Static fields used incorrectly, causing data races. Floating point types used for money amounts. JavaScript and SQL injection up the wazoo. Wildly unsafe password handling. So on, and so forth. This is the norm for most human-written software, not the exception.
As a proof-of-concept, I tried an AI rewrite of one such legacy app[1], and it is not bug free, but it notably has fewer bugs than the original. Different bugs, sure, and I'll have to iron them out after a round or two of UAT, but I'm honestly more confident with what I got from the chatbot than the code inherited from humans.
[1] Deals with money, but admittedly at a much lower level of risk and consequence than a banking app running on a mainframe.
I feel like AI has dramatically changed how complete rewrites can be considered, especially for long-lived, legacy projects.
What do you even mean by "works", specifically?
> it might have bugs, you know what they are.
Okay, so it doesn't work, you know it doesn't work, it's just that you accept the specific ways in which it doesn't work.
I've lost track of all the myriad stupid ways in which these ancient systems are hugely ineffectual without even being outright faulty.
Like airline tickets where your name is printed as "LASTFIRSTMR" in all caps and no spaces because their systems are ancient beyond belief.
Similarly, my bank statements are security-critical, because anyone with a copy of my credit card details can pull money out of my account without my express authorization. But...
... because they're stored in terrible ancient mainframe databases, the text fields all have tiny maximum lengths. Hence they're all abbreviations. Attacker-controlled abbreviations without any authenticity assurance of any kind!
I have no idea who actually transfers money out of my accounts! There are no URLs, no metadata, nothing to actually confirm the identity of the other party. Every field in a transaction record is 100% attacker-controlled and unverified by my bank.
If you look at it from the perspective of someone used to modern web security, then you realise that banking is a raging tyre in comparison. Banks literally just accept a certain rate of criminal activity and "price that in", reversing transactions when asked -- which itself can also be a criminal activity. They just shrug their shoulders.
"What can we do about this?" -- says the people that have tried nothing and are all out of ideas.
Rewrite it. The whole thing.
Use an actual database, something made in the last three decades instead of half a century ago.
Use cryptography. No, not crypto coins! I just mean a bog-standard algorithms like public-private key signing so that it is possible to confirm the source of transactions.
Etc.
I would much rather have something generated with the assistance of a modern LLM than what we have now, which is security holes big enough to drive a panamax container ship through.
It runs and accepts people's payments, which means you're not on the front page of the newspaper (not in a good way).
> ... because they're stored in terrible ancient mainframe databases, the text fields all have tiny maximum lengths. Hence they're all abbreviations. Attacker-controlled abbreviations without any authenticity assurance of any kind!
They also have to go through payment networks which are very often the limits on those things. So yeah, it sucks, but just fixing one DB isn't enough - the whole thing has to get upgraded.
> I have no idea who actually transfers money out of my accounts! There are no URLs, no metadata, nothing to actually confirm the identity of the other party. Every field in a transaction record is 100% attacker-controlled and unverified by my bank.
There is a little bit, but not much. Again, if these transfers are happening via card, it's all a terrible old fixed-length setup. Would be great if it was better, but you need Visa and Mastercard to upgrade as well. And of course there _is_ verification - most banks don't do a great job of surfacing this but they know if they've verified a PIN or CVC, or if it was contactless (in which case it _is_ unverified, but society realised we prefer the convenience there).
> Use cryptography. No, not crypto coins! I just mean a bog-standard algorithms like public-private key signing so that it is possible to confirm the source of transactions.
Obvious question then: You've made a card transaction. It is signed with the other party's private key. What does that buy you? How do you attach trust to this key? Whose is it - the payment gateway or the merchant?
> I would much rather have something generated with the assistance of a modern LLM than what we have now, which is security holes big enough to drive a panamax container ship through.
Sure, and if the LLM can rewrite enough of this system to get what you want, there's heaps of room for improvement. But this is orders of magnitude bigger in scope than rewriting your one old bit of COBOL software, it's systematic.
"It works if nobody attacks it." isn't security.
> They also have to go through payment networks which are very often the limits on those things.
For the same reasons.
> need Visa and Mastercard to upgrade as well.
They won't, and it's not worth asking them to. They're dinosaurs and will simply be replaced by a newer, more agile competitor.
It's already happening! Billions of people in Asia pay with their phones using home-grown payment systems, most of which are generally much more modern and better engineered.
> It is signed with the other party's private key. What does that buy you?
Same as what HTTPS does: attestation of identity by some trusted third-party, to some non-zero level. This could be literally just the existing CA networks and DNS domains as identity, but it could be governments, the banks themselves, etc.
I had some fraudulent transactions on my account labelled "Microsoft Subscription". It wasn't Microsoft. How can I tell?
Not even the bank knew the identity of the third party!
That's insane.
If only we had a way to solve these issues with tools capable of running Rust programs in that way. I guess every company that needs distribution / failover has a mainframe sitting in their office nowadays huh?
etc.
You could run one of these things on a mainframe, because it's a zero-downtime machine - you can swap out parts of them as they run. But fundamentally it's a singleton. It is deeply naive to believe you can trivially translate that to something running on Kubernetes just "because Rust".
Of course most companies that need distribution do manage to do that, and eventually the banks will get there too. But it isn't feasible to do that by translating their existing non-distributed COBOL code, they need a fundamental re-architecture, and that is much harder.
Sure you could keep vibe coding it but I wouldn't bet my data on that. A database needs to be rock solid.
Unfortunately that doesn't apply to all languages. LLMs are especially bad at producing code for the languages that were historically known as beginner-friendly as the training data was full of code by beginners doing what beginners do. All bets are off if you get stuck there. (Although maybe you could use an LLM to translate your code to a language that LLMs are good at!)
So either the translation produced Rust code in the "shape" of C code or the code is quite different from the C implementation.
Add to that that you need to have people proficient in Rust and also Postgres as well as the very much unknown codebase as a whole you get a recipe for pain.
If the code is going to be translated forward instead of abandoned and then rewritten, as is now completely viable via LLM, there is no reason to move to a new language at all.
I seriously don't get it though. Rust is a nice language, but so is X. However we don't see X people brigading existing projects with constant bombardment with "rewritten in X". What is that about Rust that prompts this behavior?
People see the safety as a moral superiority so it attracts obnoxious zealots.
Other languages' features and syntax aren't nearly so easy for zealots to form behind. The perception of absolute safety it puts in some people makes them crazy.
People were told for years they can't use Rust for their new projects because it hasn't been "proven" in industry yet. So the option was to sit back and wait (chicken and egg) or move to rewrite a bunch of projects so that it could actually be "proven". Not saying this is the only reason why it happens (every language has its Zealots) but it certainly makes more sense.
Due to the explosion of new programming languages over the past few decades your options are to either aggressively expand wherever possible or die out because you're not "proven".
If it _is_ 50% faster, then that's the reason
Obviously like any new database it's very risky to use so probably only used for niche use cases at first, but if it turns out to be just as reliable as postgres and faster then why not?
If you are watching this and haven't used rust: Please don't judge the language by this part of its users.
Nailed it ! There are some folks who behave holier-than-thou just because they happen to use some language. Language missionaries if you will, and they are insufferable.
These days there's little chance for a new DB to build its community using network effect. If you want this to catch on, switch to manually grinding community building ASAP gold plating the experience for a specific niche (AI can guide your priorities but will hinder your comms). Otherwise, have fun building!
Rewriten in Rust is becoming a meme now.
Surely that is not the only dimension that matters when evaluating software. Maintainability and readability, for example, are crucial for any long-lived project.
I really don't understand why this is needed outside of an opportunity to show how impressive LLMs can be when working within large codebases, but even then people in the comments are finding bizarre implementation choices that a human developer wouldn't make. I'll stick with Postgres and its - gasp - C implementation for now, thanks.
Please describe in detail what you believe this means and the mechanism by which switching from processes to threads improves performance.
Switching to threads doesn't guarantee weaker isolation, just like it doesn't guarantee better performance, but those nuances are why "switching to threading yields performance improvements" is over simplified to the point of uselessness. It simply reeks of the same kind of ignorance that used to drive statements like "rust doesn't have vulnerabilities" and "rewrite it in javascript for web scale performance".
By the way, just so you have some concept of what the actual problem is despite your resistance to education:
Simply switching from processes to threads will not yield the claimed performance increases. A 300x improvement on analytic workflows? From a direct transliteration? Your BS alarms should be going off. They should be screaming "5 Alarm Fire".
The only way they got that increase was by breaking the synchronization mechanisms that provide ACID guarantees in Postgres, otherwise a direct rewrite would expect very similar performance.
I appreciate the condescension though. Thanks for teaching stupid old me how a database works.
You're welcome, someone had to.
1. human code reviews are dead. We don't yet know what's next. Two reasons they are dead: too much code to review, and code reviewing sucks (who wants to spend their days reviewing code?) 2. Not knowing how to review LLM code is a big barrier to adoption, but bigger regression test suites (testability/evals) is almost certainly the direction. 3. There are a lot of projects that haven't moved to more modern infra because it was too hard. Now it's much easier. Sure stuff will go wrong. Sure it all has to be tested. What's new here? 4. Programming languages for LLMs are coming. 5. Projects that don't allow AI coding will be forced to come around or fade.
Separately, bit off topic:
New projects will often have LLMs built in, so non-determinism will be inherent in the project. No amount of code review will be able to eliminate that.
I'm building data + AI platform. It got complex, and I'm using AI-assisted coding to move fast. One thing that helps me was property based testing. I have a traffic generator that simulates 10 users working on my platform. I run it 24/7 and if it shows that the software survives the test (I called it "fate" after ffmpeg's CI), it's good enough to roll out. If you wrote something like that, core PostgreSQL folks would like it too, unless there's something equivalent like this. It'd be: create random tables, fill with random data, then issue randomly constructed query.
Even though I'm sure it won't be easy to convince the Postgres project to switch to Rust, I do think that trying would be time better spent.
Hopefully we get: actual formal coding rules, spec rules, design rules, contribution rules, documentation and testing rules. High Integrity development processes impose that you write all this before you start and makes sure you follow your own rules.
So. I guess... welcome everyone to explicit software and systems development processes.
Was the code for the threading model written by hand or was it translated from the WIP threading model the human PG team is busy with as part of the 2028 roadmap?
I totally understand why porting code is fun. It's kind of like when I checked out drawing books from the library as a kid and just traced the pictures because my own attempts at drawing were so bad. It gives you a feeling of accomplishment, even though you didn't actually do anything that difficult. And you do learn some things along the way.
Doing the same with an LLM probably gives you that similar feeling of accomplishment, even though you didn't actually do that much (sorry, hate to say it that way). I wonder if you learn even less in the process. Maybe you just learn different things.
Now that I think about it, even writing some code from scratch with an LLM is not much different than doing a porting project. Someone else did the hard work of creating the original programs that the LLM was trained on, and now you (the LLM really) are just porting/restating what someone else did. I hadn't thought of that before
I know it says it is not performance optimized yet, but if this succeeds, will it only bring more "memory safety" or is there a serious performance gain as well?
will it only bring more "memory safety" or is there a serious performance gain as well?
The project will die in a couple of days or weeks. You're making a mistake if you're seriously consider using this in any capacity.https://knowyourmeme.com/memes/i-dont-want-to-play-with-you-...
I wished the two phases would have been tackled in reverse order.
Well, tackling them in reverse order would require the humans behind this to develop an actual understanding of the existing code and architecture before starting the project, instead of just asking claude to do it. So, here we are.
This is usually a good example of a test case that the upstream project is not covering and can be contributed back.
Parity should be bidirectional, so definitely it is possible for both parties to benefit from it.
I'm still skeptical about LLMs and don't use them, although I can be convinced by more demonstrated examples of success.
I ain't no Rustacean - but 'unsafe' calls all over.
I remember writing a postgresql compatible DB with Opus 4.5, that used S3 as storage and local caching to make it speedy.
Ironically, Opus 4.5 is by todays standards is antique. If you have some knowledge about Databases, it goes a long way.
But you need to do it step by step. Getting the core to work, getting a Pratt parsing going. The whole pgwire protocol ... the data format ...
Step by step ...
With todays Models, your can probably get away with using /goal and telling it to make a postgresql compatible database, while having it run a few days.
Now, making a fun database test project and having it production ready! Big difference!
In fact from a porting effort this is the first blog post I would expect. Not that the hey we successfully did it.
They will ask relevant Claude skill.md
Is it cheaper to find them at compile time rather than runtime? Yes.
But it’s not an unsolved problem. Memory bugs are a known unknown.
uh-huh, sure.
you want to show off "look what the LLM can do / look what I burned a bunch of tokens on"?
you want to brag about how your LLM-generated slop is somehow more maintainable than the original because blah blah blah Rust?
here [0] is the version history of Postgres. pick a version from the past. let's say 14.x because it's the most current that's still under active support.
have your LLM implement version parity with 14.x. show off how it passes all the tests blah blah blah.
then have it upgrade your codebase to parity with 15.x, implementing whatever new features and bugfixes that includes.
and have it generate an automated test that demonstrates upgrading an actual database from LLM-14.x to LLM-15.x and verifying there's no data loss or corruption. maybe even multiple such tests, if you're feeling fancy.
then lather, rinse and repeat with 16, 17, and 18.
and show off the diffs of each version. does the LLM rewrite a huge pile of already-working code in the process of each version upgrade? does it introduce new latent bugs in the process - the kind of things the existing test suite didn't think to explicitly test for?
"I took a static snapshot of code and converted it to another static snapshot of code" is meaningless. all you're doing is bragging about having more money than good sense.
the stability and trustworthiness of software like Postgres does not come from a one-time snapshot showing tests passing. it comes from the engineering process that produces the software and its test suite.
oh, and for shits and giggles, because this same test was so illuminating with the Bun "rewrite" into Rust, here is the file with the most unsafe blocks in the codebase:
> rg -c unsafe crates/backend/parser/gram_core/src/convert_ddl.rs
128
> wc -l crates/backend/parser/gram_core/src/convert_ddl.rs
2055 crates/backend/parser/gram_core/src/convert_ddl.rs
why does a single 2000-line file have over 100 unsafe blocks?why is the parser unsafe at all?!?
let r = unsafe { &*p };
It looks as if it's building structs out of information in (mutable pointers) to other structs without an Rc in sight. Which makes sense for a C parser: you've got a table with data, so you just link to it. It's fast, and when you know you're not going to touch it, it's safe. But this doesn't make the Rust code any better than the C code.The parser was generated by c2rust. The Postgres parser is generated from yacc/bison itself so I didn't bother making it idiomatic.
but given the author/maintainer is essentially unknown, I highly doubt this will reach it's target audience. But one thing I do agree with is that postgres is long overdue for a re-write into a memory safe language.
also any real swe with more than a few years of experience knows "100% of regression suite passing" doesn't mean anything other than a neat checkmark for C-level executives.
>pgrust is licensed under AGPL-3.0
pgrust isn't licensed at all. AI generated code isn't copyrightable. Thanks for spending the tokens I guess.
https://github.com/malisper/pgrust/blob/main/Cargo.lock
What is happening.
No PRs? No Make files? I understand running tests and debugging is the workflow, but where do you log things? How do you orchestrate builds? Etc.
There might be some correlation here.
The project itself seems to be structued around 1.4k micro-crates[0] which I admit is a bit weird. Rust's compilation unit is the crate unlike C's per-file compilation unit, so if this was a 1:1 AI-assisted translation from the original Postgres source this might be an artifact of the translation.
Edit: saw the clarification in another comment. But, in that case the essential point seems to be "I'm not familiar with something, therefore it's suspect."
Too many things tests wont catch.
I'm sorry, but what is this need to just vibe code a port of an existing technology to a different language/framework/etc.? If it's just a personal challenge then sure I guess, but this surely can't be used as a real product?
Copyleft and the whole software licensing ecosystem only matter when producing that software actually requires serious human effort and dedication.
For my machine translation of SQLite to Go I added this to the README as to licencing:
Most of the code here is machine translated using wasm2go. As such, the original authors retain copyright and the original licenses remain in effect. Everything else is licensed under MIT-0.
The translator (wasm2go) has a licence chosen by, and a copyright notice from, me. Makes no sense for the translated code.
And avoid relying on direct LLM output for actual work to make sure I don't accidentally include some regurgitated snippet from an incompatible license.
It helps that LLMs struggle to write good, idiomatic code in my language of choice.
Fixed that for you. Code generated by an LLM is not copyrightable (because copyright only protects human effort), so the codebase is automatically public domain and cannot be licensed at all.
They could theoretically copyright the prompts that they used, but as that's not part of the output, and the output doesn't deterministically arise from those prompts, they'd struggle to use that to back a copyright claim.
I wonder how many "unsafe" blocks are in there...
https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...
https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...
The boolean being returned is the return value of the function. It's not used to return an error.
An unfortunate aspect is that the code has become a bit more bloated in some regards due to usage of Result, instead of an implicit elog() macro and similar. Passing Result around, in some ways as an alternative to an unwinding exception, is cleaner in some ways, but it also bloats the code somewhat.
The rewrite also could have simpler code in some cases, like
https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...
could perhaps just be
match syscache_seams::search_pg_class_full_form::call(ctx.mcx(), relationId)? {
Some(form) => Ok(form.relhassubclass),
None => {
Err(ereport(ERROR)
.errmsg(format!("cache lookup failed for relation {relationId}"))
.into_error())
}
}
but that is a smaller thing.I see a lot of MemoryContext. I am not sure how much that bloats the code (though the C code is bloated due to C's issues and problems, like re-using collections and such). Does it incur an overhead?
The Rust code is a literal translation of the Postgres code which returns the value at the end instead of an early return.
> I see a lot of MemoryContext
MemoryContext in C is used for multiple reasons: 1) performance 2) keeping track of how much memory has been allocated and where and 3) preventing memory leaks.
Reasons 1 and 2 are still relevant for Rust. The challenge is in C memory contexts are stored in a global variable. Global variables don't work well with the rust borrow checker so I opted for passing memory contexts as function arguments instead.
Super cool to see him working on this now, almost 10 years later
...but haven't dared use it for anything meaningful yet. Still feels like there is a real world gap in confidence when it comes to vibecoded rewrites.
Been wondering whether the answer is to insert a proxy...something that effectively splits traffic to a known S3 and the rewrite and compares outcomes over time. Do that for a couple different workloads for a month or so and if it's all identical then it's probably fine...
Rust:
https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...
Original:
https://github.com/postgres/postgres/blob/df293aed46e3133df3...
Usage:
https://github.com/malisper/pgrust/blob/3646a73515a5e4ac7d0b...
The return type in the rewrite is both some sort of Error tagged union that supports the Try machinery in Rust; but, it also contains a boolean that apparently must be checked; or something. It seems labyrinthical and possibly broken and terrible.
The error-tagged union is PgResult<bool> - which means it contains bool as the result if things go well. (The other part in the union is of course the error.)
In the original function also, it is returning a boolean: "bool has_subclass".
So anyway you have to check for the boolean as part of the logic. That is what it is doing.
Edit: Looking at the code again, perhaps I was mistaken, since the boolean might not have been for error handling, just the result of the function, and C's limitations regarding error handling led it to using something like elog(), apparently a macro defined in https://github.com/postgres/postgres/blob/master/src/include... .
Though often when applicable, a simple tagged union is used instead when that would document the intention better. Like, the Rust version of search_pg_class_full_form::call() returns a Some for cache hit and None for cache miss as far as I can skim, and that group of methods returning that could arguably have returned a basic enum instead with CacheHit(value) and CacheMiss. Though this is a nitpick on my part.
I have privately wondered for years, pre-AI, why Apple hadn’t paid some engineers to go off and write some comprehensive test suites and then port these to Swift. It would shut down entire swaths of memory safety bugs they have been coping with for literally decades. SO MANY of the zeroclick iOS exploits can be traced to a few fragile and vulnerable foss libraries, xkcd 2347 style.
I have a feeling that AI is rewriting everything!
This thread is enumerating all the same talking points of both sides.
DST systems such as Antithesis can definitely help.
Common pronunciations allow you to stay perfectly ambiguous about where the L goes, which aligns quite well with the name as spelled. If you do it right, nobody can tell if you're saying sequel-ite or sequel-lite or seque-lite on the one hand, or S-Q-L-ite or S-Q-L-lite or S-Q-lite on the other.
AFAIK there is no official word on how the name is intended to be read or said.
> (Hipp) How do I pronounce the name of the product? I say S-Q-L-ite, like a mineral.
> But I also hear a lot people say, "Sequel lite and SQL lite." You know, I don't care. Whatever comes off of your tongue easily is fine with me.
> (Q) But the official correct way is S-Q-L-ite?
> (Hipp) Yes, like a mineral.
https://www.listennotes.com/podcasts/the-changelog/why-sqlit...
So, he means SQL-ite, but doesn't want to proscribe this as the only way people should say it. I like all of that.
Maybe we should follow his example.
There are much better ways to write it in Rust: https://github.com/malisper/pgrust/blob/14ffab7d31a31e5ab667...
Case in point: https://github.com/postgres/postgres/blob/master/src/common/...