# Six Postgres 19 Features Your Coding Agent Does Not Know About

> Source: <https://githits.com/blog/postgres-19-coding-agents-githits/>
> Published: 2026-07-21 00:00:00+00:00

[Back to blog](/blog/)

July 21, 2026 · 8 min read

# Six Postgres 19 Features Your Coding Agent Does Not Know About

We used GitHits to explore the Postgres 19 release and surface what changed. Six features came back. A coding agent without GitHits could not reach any of them.

This post did not start with a list of features. It started with a question: ask a coding agent what is new in a database release, and does it actually know?

Postgres 19 reached beta on June 4. We connected GitHits to a coding agent and asked it to work through the release from source, then report on what was new and what it changed for anyone writing queries. The six features below are what came back. We had not picked them in advance.

Then we ran the second half of the test. For each feature we wrote the prompt a developer would plausibly type, and ran it through the same agent twice: once with GitHits enabled, once without. Same model, same prompt, fresh context, one prompt at a time so no answer could lean on another.

Without GitHits, the agent did not reach any of the six. Not partially, not with hedging. In every case it explained that the thing being asked for was not available in core Postgres, and offered the workaround that was correct before this release. Below is each prompt, both answers, and what actually shipped.

## Two management hops up an org chart

Start with a graph traversal, the kind of query you would write against an org chart.

**Prompt**

I have an

`employees`

table with a`reports_to`

self-reference. Using only core Postgres, no extensions and no separate graph database, write a query using graph pattern-matching syntax that finds everyone exactly two management hops above ‘Alice’.

**Without GitHits**

Not possible in core PostgreSQL. PostgreSQL has recursive CTEs, but no core graph pattern-matching syntax. Use a recursive CTE instead.

**With GitHits**

```
CREATE PROPERTY GRAPH employee_graph
  VERTEX TABLES (
    employees KEY (id)
      LABEL employee
      PROPERTIES (id, name)
  )
  EDGE TABLES (
    employees AS reports_to_edge
      SOURCE KEY (id) REFERENCES employees (id)
      DESTINATION KEY (reports_to) REFERENCES employees (id)
      LABEL reports_to
  );

SELECT manager_name
FROM GRAPH_TABLE (
  employee_graph
  MATCH (alice IS employee WHERE alice.name = 'Alice')
        -[IS reports_to]->()
        -[IS reports_to]->(manager IS employee)
  COLUMNS (manager.name AS manager_name)
);
```

The answer without GitHits describes Postgres as it was a year ago, and a year ago it was correct. Postgres 19 adds SQL/PGQ, the SQL:2023 property graph standard, with `CREATE PROPERTY GRAPH`

and `GRAPH_TABLE`

. A recursive CTE still works, but it answers a different question than the one asked. The prompt asked for graph syntax, and that syntax now exists.

## The last non-null value in a gappy series

Anyone working with sensor data or event streams has wanted this and hit the same wall.

**Prompt**

I have

`sensor_readings(sensor_id, ts, reading)`

where`reading`

is frequently NULL. For each row, return the most recent non-null reading at or before that row’s timestamp, partitioned by sensor, in one query with no self-joins or lateral workarounds.

**Without GitHits**

Not possible in core PostgreSQL with those constraints. PostgreSQL does not support

`LAST_VALUE(reading) IGNORE NULLS`

. This needs a workaround such as a self-join, lateral lookup, recursive query, or custom aggregate.

**With GitHits**

```
SELECT
  sensor_id,
  ts,
  reading,
  last_value(reading) IGNORE NULLS OVER (
    PARTITION BY sensor_id
    ORDER BY ts
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS latest_non_null_reading
FROM sensor_readings;
```

For most of Postgres history, “no `IGNORE NULLS`

” was simply true, and the lateral-join workaround is well documented, so the agent reaches for it. This is also a case where web search would not have helped much, since most of what is written on the subject still describes the old behavior. Postgres 19 added `IGNORE NULLS`

and `RESPECT NULLS`

to `lead`

, `lag`

, `first_value`

, `last_value`

, and `nth_value`

. The single line the agent ruled out is the answer.

## A random timestamp for test data

A small one, but the kind of thing you write often.

**Prompt**

Give me a Postgres expression that returns a random

`timestamptz`

between two given timestamps, without hand-rolling interval math.

**Without GitHits**

Not possible with a built-in timestamp-range random function. PostgreSQL has

`random(min, max)`

for numeric types, not`timestamptz`

. A random`timestamptz`

requires interval or epoch arithmetic.

**With GitHits**

```
SELECT random(
  '2026-07-10 00:00:00+00'::timestamptz,
  '2026-07-11 00:00:00+00'::timestamptz
);
```

Worth noting how much the agent gets right here. It knows `random`

gained numeric bounds in an earlier release and recalls the old signature correctly. It does not know that 19 added `date`

, `timestamp`

, and `timestamptz`

overloads, so it sends you back to epoch arithmetic you no longer need.

## Sequences during a near-zero-downtime upgrade

A question a DBA actually loses sleep over, and one where a stale answer costs you at cutover.

**Prompt**

I’m setting up logical replication between two Postgres clusters for a near-zero-downtime major upgrade. After cutover, do I have to manually resync sequence values on the subscriber, or is there a setup that keeps sequences in sync automatically? Show the setup.

**Without GitHits**

In core PostgreSQL logical replication, sequence changes are not kept in sync automatically. Before allowing writes on the upgraded subscriber, resync sequences manually, for example with

`setval('public.users_id_seq', (SELECT max(id) FROM public.users), true)`

.

**With GitHits**

```
-- publisher
CREATE PUBLICATION upgrade_pub
FOR ALL TABLES, ALL SEQUENCES;

-- subscriber
CREATE SUBSCRIPTION upgrade_sub
CONNECTION 'host=publisher dbname=app user=repl password=...'
PUBLICATION upgrade_pub
WITH (copy_data = true);

-- resync before cutover
ALTER SUBSCRIPTION upgrade_sub REFRESH SEQUENCES;
```

For years, “logical replication does not carry sequences” was dependable enough to state as a rule, and the agent states it as one. Postgres 19 changed it. Publications can now include sequences with `ALL SEQUENCES`

, and `ALTER SUBSCRIPTION ... REFRESH SEQUENCES`

brings their values across. One detail worth keeping straight: this syncs at subscribe and refresh rather than continuously, which is the shape a cutover needs. Left alone, the agent would have you scripting `setval`

for a problem the release already handles.

## Turning on checksums without an outage

The last two are quick, because the shape is familiar by now.

**Prompt**

My running Postgres cluster has data checksums disabled. How do I enable them without taking the cluster offline or running

`pg_checksums`

in offline mode?

**Without GitHits**

You cannot enable data checksums online in core PostgreSQL.

`pg_checksums --enable`

requires the cluster to be shut down cleanly; there is no online core equivalent.

**With GitHits**

```
SELECT pg_enable_data_checksums();

-- optionally throttle the background rewrite
SELECT pg_enable_data_checksums(cost_delay => 10, cost_limit => 1000);
```

For thirteen years the correct answer was to shut the cluster down. Postgres 19 added `pg_enable_data_checksums()`

and `pg_disable_data_checksums()`

, which flip checksums on a live cluster while a background worker rewrites every page. The agent gave the answer that was true until this release.

## URL-safe base64

**Prompt**

Encode a

`bytea`

to a URL-safe base64 string in Postgres, the variant using`-`

and`_`

instead of`+`

and`/`

, with a built-in and not a manual`replace()`

.

**Without GitHits**

Not possible with a built-in base64url encoder. Core

`encode()`

supports`base64`

,`hex`

, and`escape`

, but not URL-safe base64 without post-processing.

**With GitHits**

```
SELECT encode('\xdeadbeef'::bytea, 'base64url');
```

Smaller surface, same result. `encode`

and `decode`

gained `base64url`

and `base32hex`

in 19. The agent listed the old formats as though that list were still complete.

## What the six have in common

Two things are worth separating here.

The first is that the agent did not know about these features, which on its own is unremarkable. The second is more useful: it also could not tell that it did not know. Across all six prompts it answered quickly and in the same tone it uses when it is right, and it never flagged that the version might have moved. Each “not possible” meant “not possible in the Postgres I know about,” but nothing in the output marks that distinction. The answers that are wrong read the same as the answers that are right.

None of these features are obscure. All six are in the [Postgres 19 release notes](https://www.postgresql.org/docs/19/release-19.html), and we traced each one back to the Postgres source before publishing. They are ordinary additions, and they are new.

That is also why GitHits closes the gap without touching the model. Same model, same weights in both runs. Everything the agent needed was public and retrievable, sitting in the source tree the whole time. What it lacked was any reason to go looking, because it did not perceive a gap. GitHits reads the source for the version in question and puts those facts in front of the model before it answers, which accounts for the entire difference between the two answers.

Postgres 19 is a convenient example because the release is recent enough that the misses are easy to check. The same thing happens more quietly with any library, framework, or API that has shipped a version the model does not know about, where the wrong answer arrives just as confidently and you have no release notes open to catch it. The six prompts here are reproducible. Enable GitHits and run them yourself.
