neondatabase/neon
Architecture
Neon decouples Postgres compute from Postgres storage. A compute node runs a slightly patched Postgres process whose storage manager has been replaced; pages and WAL no longer live on local disk. Instead:
- The compute streams WAL to a quorum of safekeepers, which durably persist it.
- Safekeepers stream WAL to the pageserver, which decodes records, applies them via WAL-redo, and writes immutable layer files to local disk and cloud object storage.
- When the compute needs a page, it issues a
GetPage@LSNrequest to the pageserver, which reconstructs that page version from the layered storage. - A storage broker lets pageservers and safekeepers find each other; a storage controller assigns tenants to pageserver shards and orchestrates migration. A storage scrubber reaps abandoned objects in S3.
This split is what makes Neon "serverless": the compute is stateless, can be stopped, started, or scaled independently of storage, and any number of read replicas can attach to the same timeline at different LSNs.
High-level data flow
graph LR
Client[Postgres Client] -->|TLS / WS / HTTP| Proxy[proxy]
Proxy -->|psql wire protocol| Compute[Compute Node<br/>patched Postgres + neon ext]
Compute -->|WAL stream| SK1[safekeeper 1]
Compute -->|WAL stream| SK2[safekeeper 2]
Compute -->|WAL stream| SK3[safekeeper 3]
SK1 & SK2 & SK3 -->|published via| Broker[storage_broker]
Broker -->|subscribe| PS[pageserver]
SK1 -->|WAL fetch| PS
PS -->|GetPage@LSN| Compute
PS -->|layer uploads| S3[(Cloud Object Storage)]
StorCon[storage_controller] -->|shard placement| PS
Scrubber[storage_scrubber] -.->|garbage collect| S3Components and where they live
| Component | Directory | Role |
|---|---|---|
| Pageserver | pageserver/ |
Stores layer files, ingests WAL, serves GetPage@LSN, runs WAL-redo. See pageserver/src/lib.rs. |
| Safekeeper | safekeeper/ |
Durable WAL acceptor, Paxos-style consensus over WAL. Entry point safekeeper/src/bin/safekeeper.rs. |
| Storage broker | storage_broker/ |
Pub/sub mesh that lets pageservers discover the latest WAL position from safekeepers. Tonic-based gRPC service. |
| Storage controller | storage_controller/ |
Manages tenant placement and sharding across pageservers. Backed by a Postgres metadata DB (see storage_controller/migrations/). |
| Storage scrubber | storage_scrubber/ |
Offline tool that scans cloud storage and removes leaked or unreachable objects. |
| Endpoint storage | endpoint_storage/ |
Per-endpoint object store for things like uploaded extension files. |
| Compute ctl | compute_tools/ |
Supervises a Postgres process on a compute node: configures it, applies the spec, downloads extensions, hot-reloads on changes. Binary in compute_tools/src/bin/compute_ctl.rs. |
| Compute image | compute/ |
Dockerfile and VM image specs for the production compute node. |
| Postgres fork | vendor/postgres-v{14,15,16,17} |
Upstream Postgres with Neon's modifications (see docs/core_changes.md). |
| Neon extension | pgxn/neon/ |
Postgres extension that replaces the smgr with a network-backed implementation talking to the pageserver. Includes the walproposer C library. |
| Proxy | proxy/ |
TLS-terminating Postgres protocol proxy with auth, pooling, websocket tunneling, and SQL-over-HTTP. |
| Local control plane | control_plane/ |
The neon_local CLI (cargo neon) used in dev and integration tests. |
| Test runner | test_runner/ |
Python + pytest integration suite. |
| Shared libraries | libs/* |
25+ Rust crates (utils, metrics, postgres_ffi, pq_proto, pageserver_api, safekeeper_api, walproposer, …). |
Pageserver internals
The pageserver is the largest single subsystem. It manages many tenants; each tenant has many timelines (branches); each timeline owns a set of immutable on-disk layer files plus an in-memory layer where freshly received WAL accumulates.
graph TD
subgraph Pageserver
WalReceiver[WAL receiver<br/>per timeline] --> InMem[In-memory layer]
InMem -->|checkpoint| L0[L0 delta layer files]
L0 -->|compaction| L1[L1 delta layers + image layers]
L1 -->|upload| Remote[Remote storage<br/>libs/remote_storage]
Remote -->|on-demand download| L1
PageService[Page service<br/>page_service.rs] -->|read| L1 & InMem
PageService -->|reconstruct| WalRedo[WAL-redo process<br/>walredo.rs]
WalRedo -->|invokes| RedoProc[(postgres --wal-redo)]
end
Compute -->|GetPage@LSN| PageService
SK[safekeeper] -->|stream WAL| WalReceiverLayer files come in two shapes (see pageserver/src/tenant/storage_layer.rs):
- Image layers hold a snapshot of a key range at a single LSN.
- Delta layers hold WAL records for a key range across a range of LSNs.
To answer GetPage@LSN, the pageserver finds the most recent image layer for the key, then replays delta records up to the requested LSN through the WAL-redo Postgres subprocess. See Pageserver overview and Storage layers.
Safekeeper consensus
Safekeepers run a custom Paxos variant over the WAL stream. The compute embeds a walproposer library (pgxn/neon/ C code, also exposed via libs/walproposer) that proposes WAL records to a quorum of safekeepers. Once a quorum acknowledges, the LSN is durable. Pageservers fetch already-durable WAL from any safekeeper. See Safekeeper and docs/safekeeper-protocol.md.
Sharding and orchestration
A single tenant can be sharded across multiple pageserver nodes for horizontal scale. Sharding is keyed by relation block ranges. Placement is managed by the storage controller (storage_controller/), which keeps shard-to-pageserver assignments in a Postgres metadata DB and exposes a control API. Compute nodes route GetPage@LSN to the right shard via the pageserver client (pageserver/client/, pageserver/client_grpc/). See Storage controller.
Connection edge
The proxy accepts connections in three flavors:
- Plain Postgres-over-TCP with SNI-based project routing.
- Postgres-over-WebSockets for environments that cannot open arbitrary TCP.
- SQL-over-HTTP (
/sqlendpoint) and a REST broker mode that authorizes JWTs and forwards rows as JSON.
Auth backends include console (the production control plane), postgres (a local Postgres used for development), and link / web (passwordless email link). See Proxy.
Cloud storage
libs/remote_storage abstracts S3, Azure Blob, GCS, and a local-filesystem backend (LocalFs) used in tests. Pageservers, safekeepers, and the scrubber all use this crate. Configuration is documented in docs/settings.md.
Observability
All Rust services use tracing with a JSON formatter (libs/tracing-utils), Prometheus metrics via the metrics crate (libs/metrics), and OpenTelemetry/OTLP traces. See How to monitor.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.