neondatabase/neon
The vendored Postgres fork
vendor/postgres-v{14,15,16,17} are git submodules pointing at neondatabase/postgres branches that hold lightly patched copies of upstream PostgreSQL. They are the source from which Neon's compute nodes (and the WAL-redo subprocess used by the pageserver) are built.
The exhaustive technical writeup of every patch is docs/core_changes.md. This page summarizes what kinds of patches exist, why they exist, and how they're maintained.
Why patches at all?
Most Neon-specific behavior lives in the pgxn/neon extension. But Postgres's extension API does not yet expose every hook Neon needs. The patches add the hook points; the extension uses them. The long-term plan stated in docs/core_changes.md:
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, some patches have been retired as upstream landed equivalent functionality (the v17 streaming-read work, for example). Others remain.
Categories of changes
docs/core_changes.md groups them into:
Changes needed in the compute node
- Prefetching. Neon's latency to the pageserver is much higher than to local disk, so aggressive prefetching is critical. Patches add prefetching paths for seq scans, index scans, and bitmap scans. v17's streaming-read work is expected to absorb some of this.
t_cidin heap WAL records. Upstream's heap WAL records don't include the inserter's command id; replicas don't need it because they never reread their own row mid-transaction. Neon does, because the pageserver reconstructs page versions on demand and a still-running transaction may reread its own newly-inserted rows. The patch widens heap WAL records by 4 bytes.- Custom WAL records via
pgxn/neon_rmgr. Hooks for registering new WAL resource managers (used for things like Neon-specific catalog-state changes). - Walproposer hooks. Hooks at WAL insertion to feed the walproposer in
pgxn/neon. - smgr hooks. Hook points for
smgropen,smgrread,smgrwrite,smgrnblocks, etc. so thepgxn/neonextension can install a pageserver-backed implementation. - Backpressure hooks. A hook in
XactLockTableWaitand friends so the compute can stall when the pageserver/safekeepers are too far behind. - Initdb and bootstrap. Smaller adjustments so a freshly-bootstrapped Postgres can boot from a basebackup that itself came from the pageserver rather than from
pg_basebackup.
Changes needed in the WAL-redo subprocess
--wal-redomode flag. A startup mode that runs Postgres just enough to apply WAL records to a base page image.- Read records over a pipe. Replace WAL reading from disk with reading from a pipe.
- Sandbox setup. Hooks so the harness in
pgxn/neon_walredo/can install seccomp filters and limit syscalls.
For each patch class, docs/core_changes.md documents the affected files in upstream, why the patch is needed, and the planned path to retire it.
How the multi-version build works
Makefile declares POSTGRES_VERSIONS = v17 v16 v15 v14 and then loops over them. postgres.mk (included from the top-level Makefile) defines the per-version build rules:
postgres-install-v17: # configure + make + install vendor/postgres-v17 into pg_install/v17/
postgres-headers-install: # alias for the headers needed before building Rust postgres_ffi
neon-pg-ext-v17: # build pgxn/* against pg_install/v17
walproposer-lib: # build a static walproposer.a against v17The Rust libs/postgres_ffi/ crate has per-version submodules so it can interoperate with all four ABIs at runtime. The pageserver, when running the WAL-redo subprocess for a tenant, picks the Postgres binary matching the tenant's pg_version.
Updating Postgres
docs/updating-postgres.md (in the repo) describes the workflow:
- Open a PR on the
neondatabase/postgresfork that bumps the upstream merge target. - Resolve any conflicts by re-applying Neon patches. Most patches are stable; a few areas (smgr hooks, WAL record format) are higher friction.
- Run the matrix in CI.
- Once green, update the submodule pointer in
vendor/postgres-vXXhere. - Cross-check
pgxn/neon/neon_pgversioncompat.hfor any new shims needed.
Adding a brand-new major version (e.g. v17) goes through the same flow plus a new vendor/postgres-v17/ submodule and a new entry in POSTGRES_VERSIONS.
Where to read
docs/core_changes.md— exhaustive patch-by-patch description.docs/updating-postgres.md— upgrade workflow.pgxn/neon/neon_pgversioncompat.h— compile-time shims for the 4 supported versions.- The submodule itself (
cd vendor/postgres-v17 && git log) for the actual patches.
Why this matters for contributors
Most Neon contributors never touch the vendored Postgres. The exception is the compute team. If you find yourself in vendor/postgres-v*, expect:
- A separate PR on
neondatabase/postgrespaired with your PR here. pg_install/rebuild times in the multi-minute range.- Tests across all four supported PG versions (CI handles this automatically).
- A reviewer who is paying close attention to whether the change can instead be done as an extension hook addition, since that's the long-term plan.
See also
- Neon Postgres extension — the consumer of these hooks.
- WAL redo — uses the
--wal-redomode. - Pageserver / Page service — receives the smgr-hook traffic.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.