neondatabase/neon
Postgres core changes
This page is the abridged version. The exhaustive treatment, with rationale and "how to retire this patch" notes for every change, is docs/core_changes.md.
What gets patched and why
Neon delivers a (nearly) drop-in Postgres compute by making targeted changes to upstream Postgres and then implementing the bulk of new behavior in the pgxn/neon extension. The patches add hooks; the extension uses them.
Compute-side changes
| Change | Why |
|---|---|
| Prefetch hooks in seq scans, index scans, bitmap scans | Network latency to pageservers is high relative to local disk. Prefetching paper-overs the round-trip cost. v17 streaming-read work is starting to absorb some of this. |
t_cid in heap WAL records |
Upstream WAL doesn't carry the inserter's command id. Vanilla Postgres doesn't need it on the standby because the standby never re-reads its own row mid-transaction. Neon does — the pageserver materializes pages on demand, including for in-progress transactions. The patch widens heap WAL records by 4 bytes. This makes Neon WAL incompatible with vanilla Postgres. |
| Custom resource manager (rmgr) registration | pgxn/neon_rmgr registers Neon-specific WAL record types. The hook has been upstreamed in newer Postgres versions; the patch is shrinking. |
| WAL insertion hooks | The walproposer inside pgxn/neon needs to be called as WAL is inserted, not just during commit. |
| Storage manager (smgr) hooks | Postgres's smgr layer was not pluggable enough for pgxn/neon to install a network-backed implementation purely from an extension. The patches add hook points. |
| Backpressure hooks | XactLockTableWait and friends gain a hook so the compute can stall when storage falls behind. |
shared_preload_libraries and bootstrap timing tweaks |
Neon's extension needs to be loaded before normal startup, and at slightly different lifecycle points than upstream supports. |
WAL-redo-side changes
The pageserver runs Postgres in a special "WAL redo" mode. This needs:
| Change | Why |
|---|---|
--wal-redo startup flag |
A mode that runs only enough Postgres to apply a WAL record over a base page. |
| WAL records read from a pipe | Replace WAL fetching from disk with reading framed records from stdin. |
| No real PGDATA | The redo subprocess runs without a meaningful data directory. |
| Sandbox hooks | The harness in pgxn/neon_walredo/ needs hooks to install seccomp filters and a minimal syscall set. |
How the patches are kept current
vendor/postgres-v{14,15,16,17} are git submodules pointing at branches in the neondatabase/postgres fork. Each branch is upstream + Neon's patches.
When upstream releases a new minor version, the workflow (see docs/updating-postgres.md):
- Rebase the Neon patch series onto the new upstream.
- Resolve conflicts (most patches are stable; the smgr-hook and WAL-record patches are the highest-friction).
- Open a PR on
neondatabase/postgres; CI on this repo points at the submodule pointer in the PR. - Once green, update the submodule pointer here.
When upstream releases a new major version, additionally:
- Add a
vendor/postgres-vXX/submodule. - Add
vXXtoPOSTGRES_VERSIONSinMakefile. - Ensure
pgxn/neon/neon_pgversioncompat.hhas shims for any new APIs. - Add
vXXsubmodules inlibs/postgres_ffi/and per-version constants.
What's not patched
docs/core_changes.md ends with:
The long-term goal is to eliminate all these changes, by submitting patches to upstream and refactoring code into extensions, so that you can run unmodified PostgreSQL against Neon storage.
In practice, the patch set has shrunk over major versions as upstream has accepted Neon-driven hooks. The remaining patches are the ones that fundamentally change wire formats (the t_cid patch) or that haven't yet been negotiated upstream.
What to do as a contributor
If you're tempted to patch upstream Postgres to add a feature:
- First, try to do it in
pgxn/neonas an extension. The set of available hooks is large; checkpgxn/neon/neon.c(_PG_init) for the hooks already used. - If you need a new hook, add a minimal hook to upstream and use it from the extension. A small, generic hook is much more likely to be accepted upstream than a Neon-specific patch.
- Document the change in
docs/core_changes.mdwith a "How to get rid of the patch" section, even if the path is "submit to upstream and wait." - Open a separate PR on
neondatabase/postgreswith the change, and a paired PR here that updates the submodule pointer. - Add a per-version shim in
pgxn/neon/neon_pgversioncompat.hif the change needs version-specific code.
See also
docs/core_changes.md— the long-form, patch-by-patch description.docs/updating-postgres.md— upgrade workflow.- Postgres fork — repository layout.
- Neon Postgres extension — what uses the hooks.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.