Looking Forward to Postgres 19: Epilogue
The future of Postgres is bright. So bright in fact, that I spent almost a dozen posts expounding on the upcoming features it would bring, with veritable stars in my eyes. Unfortunately, while I was out counting my chickens, it would seem some of these exciting new features failed to hatch.
How, and perhaps more importantly why that happened, deserves some investigation.
A Call to Arms
On August 25th of 2026, Robert Haas opened a pgsql-hackers thread called "scary patch contest" that opened like this:
"I asked Claude to evaluate which v19 patches were the scariest based on the number and type of bugs fixed post-freeze."
Uh oh.
This thread immediately became a hotbed of discussion. I took notice because I already had to add a disclaimer to my Syntax Potpourri article to note that the GROUP BY ALL syntax had been reverted. I started to worry what else might be on the chopping block, and I was right to be concerned. His full list consisted of, but wasn't necessarily limited to:
RI fast-path FK checks / batching
REPACK / REPACK CONCURRENTLY
Online data checksums
UPDATE/DELETE FOR PORTION OF
SQL/PGQ property graphs
postgres_fdw statistics import
Reasons included: too many revisions too close to the desired release, unexpected security issues that couldn't be addressed soon enough, patches being too "half baked" in general, and more. Indeed, many of these patches began to fall like leaves in Autumn. Let's follow the bouncing ball of relatively major reverted patches both before and after his thread started.
Non-text output formats for
pg_dumpall, reverted by Andrew Dunstan in commit 7ca548f23a on June 15th.GROUP BY ALL, reverted by Tom Lane in commit 372b8d1adb on July 17th. I wrote about this patch in Syntax Potpourri.ALTER TABLE MERGE / SPLIT PARTITION, reverted by Alexander Korotkov in commit 3e8bcc8644 on August 27th. This feature was the entire point of Split Personality.SQL/PGQ property graphs, reverted by Peter Eisentraut in commit 2b9e1aff4d on September 7th. Particularly notable because it unwound 47 commits from both
REL_19_STABLEandmaster.The batching layer of the RI fast-path foreign key patches, reverted by Amit Langote in commit 25649d6e79 on September 10th.
The
pg_get_role_ddl(),pg_get_tablespace_ddl(), andpg_get_database_ddl()functions, reverted by Andrew Dunstan in commit db169985c1 on September 12th. These functions featured prominently in Cult of Functionality.
That's two of the six in the list, plus several I covered in my "Looking Forward to Postgres 19" series. Whether or not Robert's thread contributed to this "unraveling" of so many seemingly settled features is moot. The veritable carnage continues even while I write this article.
I wonder if it had to be this way.
The Course of a Year
Postgres ships a major version about once a year.
The machine behind that cadence is the commitfest, a scheduled period where submitted patches get continuously reviewed until they're accepted, rejected, or the commitfest ends. These determine whether a feature, fix, document update, or anything else makes it into Postgres at all. The process is as ruthless as it is efficient.
Patch review itself is open to anyone. I've even been known to dabble in the process on occasion. Only a committer can apply or reject a patch, so reviews are generally just more feedback taken into consideration. When the commitfest ends, anything still waiting on its author with at least one review becomes "Returned with Feedback". Otherwise, a patch counts as "active" if it's had email traffic in the last 30 days and hasn't been failing CI for more than 21.
The Submitting a Patch wiki page is a great starting place for those interested in joining the fun. Keep patches concise, submit before the start of a new commitfest, and get new functionality in before the feature freeze. The principal ask is that submitters also review; reviews on your patch are the participation trophy for keeping review traffic flowing.
The feature freeze for Postgres 19 was April 8th of 2026. After that comes beta, which the project defines as feature-frozen. Then it says this:
Features are subject to changes that are backwards incompatible at any time during the development of the betas, and could possibly be removed altogether.
There's still going to be tumult as patch feedback rolls in. Sometimes dramatic changes are necessary to save the patch, fix some edge case, or plug a security vulnerability. And of course, committers may pull the patch outright. That process is what caught and eventually rejected so many patches during the most recent round of review.
Lowered Expectations
Let's look at a couple of these patches a bit more closely, starting with GROUP BY ALL.
Chao Li reported on June 29th that the feature took a separate branch inside transformGroupClause() which skipped the logic copying operator semantics from a matching ORDER BY item. A query with an explicit grouping column and ORDER BY a USING operator(pg_catalog.*<) results in two rows, while GROUP BY ALL returns one.
While a fairly obscure edge case, Tom Lane chimed in a couple of weeks into the thread:
"I don't have a lot of faith that there aren't other comparable bugs lurking. I think we really ought to take a step back and redesign this code..."
He went on to note that such a redesign was a large change to take on post-beta2, and that the path of prudence was probably to revert GROUP BY ALL for v19 and try again for v20.
Daniel Gustafsson agreed, though he expressed notable disappointment:
“Maybe so, it's a bit of a shame since this is a really neat bit of syntax but fixing incorrect query results post beta2 does carry the smell of most things potentially lurking in the shadows.”
Gustafsson prepared the revert while preserving the incidental doc cleanups that had ridden in with the original commit. Lane said he'd wait a day or so to see if anyone wanted to appeal, then pushed with the comment "Hearing nothing, pushed." Darn.
Then came SQL/PGQ where the same scrutiny produced a much more dramatic removal. Devs discovered that the feature enforced its invariants only at CREATE time. Add a primary key, create the property graph, drop the key, and the graph remains. Add a column so the label property counts line up, create the graph, drop the column, and watch a working GRAPH_TABLE query start failing.
Melanie Plageman, wearing her finest Release Management Team hat, put it this way:
“We are most concerned that there are several reported issues that pose design and behavior questions that the community and patch authors have yet to resolve. We feel that if any desired behavior is still unsettled, there is insufficient time to fix these in time for the release.”
Ashutosh Bapat made this observation even earlier:
“If we do that in PG 19, it may need a catversion bump - since a property graph created before the change will have those attributes and that after the change won't.”
Anything still needing a catalog version bump four months after feature freeze doesn't belong in v19. That should have led to an automatic revert once discovered in the middle of a code freeze. All the other discussions for the other pulled features had similar stories, that some critical flaw had made it past initial review.
Why did this particular release cycle produce so many such flawed patches? Or was the problem something else?
Danger, Will Robinson!
I have a theory. Thanks to the aid of AI, contributors can submit more patches per cycle than in previous years. Further, each patch now undergoes far more exhaustive automated vetting than before. It's the Cathedral and the Bazaar encountering an onslaught of thousands of tireless automatons constantly scouring patches for faults. It's inevitable then, that more patches will implode.
In Robert's original "scary patch contest" thread, Zsolt Parragi reported running a Fable audit that identified 22 reproducible issues after completing only 30% of its initial checklist. Later, divulged further in the PGQ thread:
"My claude feature-cross check analysis also finished, and a significant amount of issues it reported on master are related to PGQ. ... But even if some of them are end up being false reports, the number of them itself is significant."
Again in the "scary patch contest" thread, Melanie Plageman put up a similar theory as I did:
"One thing that I'm wondering is if the ease with which LLMs allow people to pressure test features means we are finding more bugs sooner than we have in the past."
Amit Kapila echoed her sentiments a bit later:
"Now, with AI it is relatively easier to understand the code and find the problems. So more people are able to find and provide the solution to problems."
Richard Guo expressed some amount of skepticism about AI’s role in the shenanigans:
"I expected that AI assistance would make new features more stable by feature freeze, but it seems that that hasn't turned out to be the case."
I would argue this is expected as LLMs improve. What issues they didn't find a few months ago are now obvious to the more advanced models. There was no Claude Fable by the April 8th feature freeze for Postgres 19.
Daniel Gustafsson reflects my take on that:
"Keep in mind that most (if not all) large features in 19 were written, reviewed and tested, before AI tools were either available or even remotely as good as they are now."
Finding bugs early is the best outcome. But this additional scrutiny is now threatening to eject patches that would have survived in the past. Historically, several of these bugs would have surfaced months later and been fixed with a dot release, scheduled or otherwise. Instead, there's an opportunity we didn't have before: push the release of Postgres 19 a bit further out, or remove iffy patches to maintain standard release cadence.
Decisions, decisions.
Up For Grabs
Before making that kind of assessment, let's look at another patch that tells a slightly different story.
Amit Langote posted a rework of the RI fast-path foreign key code on August 18th and asked for review. Noah Misch, the only reviewer on the list with real design context on that code, essentially abdicated, citing ENOTIME:
"I won't be able to review this. The list should consider it up for grabs."
So who picked it up instead? Nobody. Not that day, not that week. Two days later Langote committed the patches anyway, reasoning that since they fixed live bugs, sooner was better than later. He closed the open item on the 22nd, and it stayed closed for about four days.
What reopened it? The batching layer holds a set of pending foreign key checks, and something in the trigger machinery moves underneath it while that batch is still open. A nested SET CONSTRAINTS ... IMMEDIATE opens a firing cycle without opening a new query level, and the new cache key can’t tell the difference. SET CONSTRAINTS ... IMMEDIATE reports success for a constraint it never actually checks, and the orphan row reaches commit. ALTER TABLE run from inside a trigger gets to the same orphan row by a different road, sitting under a constraint the catalog considers valid. Two bugs for the price of one!
Silent foreign key corruption, from a review nobody had time to do.
Every one of those bugs was eventually fixed. Fixing bugs was never the problem. Langote's own summary on September 3rd, which opens the revert thread for the fast-path batching patch, goes into more detail:
“The batching fixes are considerably more concerning than those to the underlying per-row fast path, because they have repeatedly had to address how a live batch of pending checks interacts with trigger-firing cycles, subtransactions, deferred constraints, and SET CONSTRAINTS, rather than merely correcting isolated implementation errors. Missing one such interaction can leave a foreign key check buffered and never performed, allowing a violating row to be committed without an error.”
Robert Haas chimed in a few days later:
“I think batching in this context intrinsically requires changing the timing of trigger firing, and that is risky because (1) important things may be different at the two timings, such as the choice of snapshot, and (2) the change in timing may be user-perceptible in some way.”
There was a bit more back-and-forth in the thread like this, and Langote finally pushed the changes on the 10th. So v19 keeps the per-row fast path and loses the batching, and master keeps both while batching gets another year to settle. While an acceptable conclusion, reaching it took three weeks and four committers, all because one reviewer had no time in August.
That kind of churn reflects my original thesis. Let's look at the commitfest stats:
PG19-1 · PG20-1 · PG19-2 · PG20-2
| Commitfest | Patches | Committed | % Committed | Withdrawn |
|---|---|---|---|---|
| PG19-1 | 388 | 139 | 36 | 21 |
| PG20-1 | 628 | 190 | 30 | 51 |
| PG19-2 | 307 | 69 | 22 | 7 |
| PG20-2 | 526 | 91 | 17 | 24 |
That's a 62% jump in submissions against a falling commit rate, with withdrawals more than doubling from 21 to 51. Even though it's still early in v20's release cycle, we already see 24 withdrawn patches as well.
The "scary patches" thread also reflects a current of developer overload. Andrey Rachitskiy suggested that reviews are easy to come by, but committer attention is not. David Rowley said he'd never had fewer free cycles and argued on that basis that the revert bar should sit a little lower this year than usual. Haas conceded the shortage was real for him too, then countered that shipping an unusually buggy release would probably be counter-productive regarding review bandwidth.
By September, that shortage had stopped being an argument on a mailing list and started showing up on the calendar. Too many patches, too little time.
Still Marked TBD
The schedule is the hardest evidence that something is off-cadence this year. The open items page lists four betas: Beta 1 on June 4th, Beta 2 on July 16th, Beta 3 on August 13th, and Beta 4 set for September 24th. RC 1 and GA are both "TBD" five months after the feature freeze. Postgres 18 shipped three betas and then went straight to a release candidate.
The “open items” page history is also a thin veil over some extra chicanery. A wiki edit on September 3rd references a "resolved before 19rc1" section that no longer exists on the page. That suggests an RC1 section was prepared and then rolled back into a fourth beta instead. Beta 3 also remains the most recent project news item, so v19 stands at three shipped betas so far.
The roadmap page still proclaims the next major release is planned for September 2026 while I write this. Bruce Momjian's word for the situation in the "scary patches" thread was "unprecedented", and I tend to agree.
Joshua Drake closed the thread with a suggestion to shift v19 to Spring 2027. He argued that the volume of reverts under discussion had already lowered confidence in the release whether or not they happened. That it makes more sense to "Allow the features to mature..." None of his customers have claimed they were blocked on 19, and most weren't even on 18 yet.
Nobody replied. The "scary patch contest" thread ends there while its echoes live on.
Fingers Still Crossed
This series celebrated ten feature categories that excited me when I scanned through the changelog. Most of them are still in the tree. For now.
I do owe a number of concessions, though. "Syntax Potpourri" said of GROUP BY ALL that I'm personally never going back. That you should scramble to download Postgres 19 purely on the strength of that article. Well, that feature is gone. As is the ability to syntactically MERGE and SPLIT partitions. Lost too is the ability to introspect role, tablespace, and database DDL. The jury is still out on how many other features will survive.
My Checksums For All post told readers to restore a backup, time the conversion, vary the I/O knobs and build a production playbook, because Postgres 19 was coming very soon. That advice still stands and the feature is still in the tree, but "very soon" has not aged especially well.
Despite all of this, I'm cautiously optimistic that v20 should look more like a normal year, even if the schedule ends up permanently shifted by a few months. Unlike with v19, the current patches were written under this level of intense scrutiny from the beginning instead of meeting it months after the fact. Of course, there's also the chance that we see another giant leap in AI capabilities that similarly dismantles the current crop of patches. And there’s no long-term answer to core committers feeling overwhelmed. Time will tell.
What I do know is that Postgres 19 is currently in a kind of Limbo. We are definitely in untested waters for the time being. I'll keep updating my past articles to reflect the state of any reverted patches, but I'm keeping my fingers crossed that won't be necessary.
Regardless of how this all turns out, I'm sure Postgres will maintain its reputation for quality when 19 is finally released. Especially after watching the mailing lists through this ordeal; this is a community that clearly values correctness and stability above all.

