neondatabase/neon
Pageserver API
The pageserver exposes three distinct API surfaces:
- The page service —
GetPage@LSN, basebackup, and friends. Two transports: libpq replication and gRPC. - The HTTP management API — used by the storage controller,
pagectl, and integration tests. - The upcall handlers that pageservers call on the storage controller (covered briefly here for context).
Page service (data plane)
libpq variant
A compute connects to the pageserver as if it were starting a Postgres physical replication. It then issues neon-specific copy-mode messages defined in libs/pageserver_api/src/models.rs. The wire framing is Postgres's libpq replication framing; the message payload bytes are Neon's.
Server-side handler: pageserver/src/page_service.rs (~4.7k lines).
The opcodes:
| Op | Request | Response |
|---|---|---|
GetPage |
(tenant_id, timeline_id, key, lsn) |
(page_image) |
Exists |
(rel, lsn) |
bool |
Nblocks |
(rel, lsn) |
u32 |
GetSlruSegment |
(slru_kind, segno, lsn) |
bytes |
DbSize |
(dboid, lsn) |
u64 |
Plus a basebackup request (initiated by Postgres replication command START_REPLICATION) which receives a tar stream.
gRPC variant
pageserver/page_api/proto/ defines a tonic-based gRPC service with the same logical operations. The proto definitions are organized as one service with streaming methods for batched requests.
Why gRPC: easier streaming/cancellation, easier non-Postgres consumption (e.g. lambda runtimes), HTTP/2 multiplexing over fewer TCP sockets. The libpq variant is not going away — both are supported.
Routing to the right shard happens in pageserver/client_grpc/.
HTTP management API
Served on a separate port (default 9898). Spec at pageserver/src/http/openapi_spec.yml. Mounted via axum in pageserver/src/http/routes.rs (~4.3k lines).
Sample of the routes (full list in the spec):
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/status |
Liveness / version. |
GET |
/v1/tenant |
List attached tenants. |
POST |
/v1/tenant |
Create a tenant (idempotent). |
POST |
/v1/tenant/{tenant_id}/attach |
Attach a tenant. |
POST |
/v1/tenant/{tenant_id}/detach |
Detach a tenant. |
DELETE |
/v1/tenant/{tenant_id} |
Delete a tenant. |
GET |
/v1/tenant/{tenant_id}/timeline |
List timelines. |
POST |
/v1/tenant/{tenant_id}/timeline |
Create a timeline (root or branched). |
DELETE |
/v1/tenant/{tenant_id}/timeline/{timeline_id} |
Delete a timeline. |
POST |
/v1/tenant/{tenant_id}/timeline/{timeline_id}/checkpoint |
Force a checkpoint. |
POST |
/v1/tenant/{tenant_id}/timeline/{timeline_id}/compact |
Force compaction. |
POST |
/v1/tenant/{tenant_id}/timeline/{timeline_id}/gc |
Force GC. |
GET |
/v1/tenant/{tenant_id}/timeline/{timeline_id}/layer |
List layer files. |
GET |
/metrics |
Prometheus metrics. |
GET |
/debug_endpoints |
Various tenant/timeline diagnostic dumps. |
PUT |
/v1/failpoints |
Inject a failpoint (testing-only build feature). |
The storage controller is the primary client of this API in production. See Storage controller API for the API the controller exposes that wraps these calls.
Upcalls (pageserver → storage controller)
The pageserver calls /upcall/v1/re-attach and /upcall/v1/validate on the storage controller:
re-attach— at startup, the pageserver tells the controller "I'm here," and the controller responds with the list of tenants it should attach (with their current generation numbers). This is the generation-handshake mechanism that fences stale instances.validate— periodically, the pageserver re-validates that a tenant's generation hasn't been bumped underneath it.
The handlers live in storage_controller/src/http.rs.
Authentication
JWT Bearer tokens are required for all HTTP and page service endpoints in production. Scopes:
pageserverapi— full HTTP management access (used by the storage controller).tenant— limited per-tenant access (used by per-compute clients of the page service).safekeeperdata— used by the WAL-receive handler.
In --features testing builds, JWT checks can be disabled for unit tests.
Clients in the repo
| Crate | Surface | Notes |
|---|---|---|
pageserver/client/ |
HTTP + libpq page service | The mature, libpq-flavored client. |
pageserver/client_grpc/ |
gRPC page service | Newer; includes shard-routing logic. |
pageserver_api (libs/pageserver_api/) |
Shared types | The crate that holds the request/response models used on both ends. |
Versioning and stability
- HTTP routes are versioned (
/v1/). Breaking changes go through a new version prefix; in practice this has been rare. - The libpq message format is versioned via a feature negotiation at handshake time. A new client can talk to an old pageserver by falling back to the older message format.
- The gRPC API is in active development; expect occasional breaking changes until it stabilizes.
See also
- Pageserver / Page service
- Storage controller API
pageserver/src/http/openapi_spec.ymlfor the full OpenAPI spec.pageserver/page_api/proto/for the protobuf definitions.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.