Book a call
← THE LAB

Postgres 19 cut its headline feature days before release

PostgreSQL 19 pulled SQL/PGQ — its headline graph-query feature — 47 commits reverted days before release. Why shipping without it was the right call.

Open in ClaudeOpen in ChatGPT

7th September 2026 — PostgreSQL dropped its flagship feature before shipping. The most important thing that was supposed to be in Postgres 19 — native support of graph queries — has been removed. It's not being postponed with a future patch, but completely withdrawn. 47 commits have been reverted — both the feature itself and every subsequent fix from March. So Postgres 19 ships without it, and the soonest we see it back is in Postgres 20, in about a year from now.

Usually, minor things are quietly removed during June, but this was the main headline, so we thought it's worth to highlight.

What has been removed?

It's called SQL/PGQ and is a standardised way of querying property graphs using existing data in Postgres. In short, with it you don't need to create a graph database, but can ask graph questions against an already existing database by pointing at its tables — rows become vertices, foreign keys become edges (with names) — and traversing the graph via pattern matching instead of joining the same table multiple times. Something like this:

SQL
CREATE PROPERTY GRAPH org
  VERTEX TABLES (employee LABEL employee)
  EDGE TABLES (
    employee AS reports
      SOURCE KEY (empno) REFERENCES employee (empno)
      DESTINATION KEY (mgr)   REFERENCES employee (empno)
      LABEL reports_to
  );
SQL
SELECT manager_name
FROM GRAPH_TABLE (org
  MATCH (e IS employee WHERE e.name = 'JONES')
        -[IS reports_to]-> (m IS employee)
  COLUMNS (m.name AS manager_name)
);

And this is what we're not going to have in Postgres 19. It was a really cool feature — a kind of thing that releases are built around — so it's not just about the removal, but what has been removed.

Why remove something that was already committed?

Despite no one pointed a single critical bug, the project wasn't keen to release it. It was implemented by Peter Eisentraut and Ashutosh Bapat in March, 122 files changed, almost 15k lines, and then it was being patched throughout the summer. The threads on the mailing list raised concerns about the design and the foundations, more than about any single crash. For example:

To me, this class of problem seems completely unacceptable in a committed feature… There's just a big design gap here.

— Robert Haas

At this point I'd be willing to bet dinner that if we ship it in v19 there will be post-release bug discoveries that are unfixable until v20.

— Tom Lane

Andres Freund pointed at issues with the locking behaviour. So people were concerned about the foundations rather than an actual bug, and there was a deadline. Also, given how many security fixes this cycle carried (which makes project more sensitive to anything that might be risky), it's been a season when a few similar decisions were being made consistently, eg:

A partition merge-and-split feature had been removed 11 days earlier, on the 27th of August, with a commit message that reads:

multiple design issues which are too late to address in this release cycle

The most telling thing about this particular removal, though, is that even the author didn't fight back. You can see Peter's "Ok, let's do it." on the thread. If someone had a 15k-lines feature removed, especially their own flagship thing, we'd expect them to not let it go easily, but he did. It's a sign this was really hard for him, and — given how much he has been already involved in Postgres releases — if someone like Peter thinks we shouldn't release it, that means a lot.

Isn't "it compiles and passes review" the definition of ready?

But anyway, what matters is not only that the project decided to remove this feature (which is a normal thing projects do, actually — releasing software is hard, and sometimes you need to change your mind), but what they decided to remove. Not every removal is equal, and the scale here is substantial: not just the 15k-line feature itself, but every patch built on it since March.

And it's not only a theoretical "they could have released it" — for a couple of months this really was in the new features: it got merged, reviewed, passed tests, had two authors behind it, and had its place in the release notes. It was ready by every technical aspect. But Postgres is not a robot that spits out releases on demand — it's a group of people, and they decided that this wasn't ready. Not ready in a way that makes it hard to point a finger at a failing test, but ready technically and not trustworthy for production; ready in a way that makes the ultimate decision very hard. We'd say this is the most challenging ship/don't-ship decision — not due to a visible bug, but because the foundations don't feel right, you can't be sure what else is hiding, the time to fix it properly is gone, and you still won't put your name on it.

Also, it's a sign of maturity to be able to make such decisions without a bullet-pointed report. Being senior often means making decisions based on a general impression, even if you can't articulate every aspect of it; juniors need a test to fail to decide not to ship something. And that kind of "not-yet" reasoning is not easy and doesn't come for free — it's the most significant part of what delivery management is about. Nobody can hold an entire system in their head, so this kind of judgement is not about remembering every detail, but rather about feeling if something doesn't fit, even if you can't point where exactly. And that's what we'd have decided here.

Build half a product, not a half-assed product

But anyway, the project has removed a substantial part of the upcoming release, so it's worth looking at it from another perspective: how they've reduced the scope, keeping the quality. In Rework, Fried and Heinemeier Hansson write:

Build half a product, not a half-assed product

That's what Postgres have done here, at the scale of a global database. They could have released Postgres 19 with its main feature, but instead released Postgres 19 without it, so it's less complete, but more trustworthy. A whole version you can't fully trust is worth less than a smaller one you can. The more people were looking forward to using the graph queries in Postgres 19, the more they benefit from the project not releasing a shaky version.

Because an unstable feature that others depend on doesn't stop being a problem once the release ships — it becomes an extra load for the next two years. We can delay it, so we do.

The freeze rewards getting in; shipping is deciding what's ready

The date is important here, because it puts pressure in one direction: commit before the freeze, get the slot, make the headline. But the freeze is only about eligibility — it's not a release itself. It's just a line that says "we might release this in a few weeks", and "might" is a big word here, as the decision to ship is made later, less visibly, based on actual quality, not based on the release notes entry. And these two things diverge more often than release-note enthusiasm allows.

Postgres 19 is a visible example of a mature project keeping that separation — better in a year, so it waits a year. Not being conservative for its own sake, but in favour of the work itself.

RELATED WRITE-UPS