neondatabase/neon
Endpoint storage
Endpoint storage (endpoint_storage/) is a per-endpoint object store, added in April 2025. It serves files that are scoped to a single Neon endpoint (a specific compute) — most prominently uploaded Postgres extension files, plus other per-endpoint blobs the compute may need.
It's the youngest top-level service in the repo and the smallest by code volume.
Why it exists
Before endpoint_storage, on-demand extensions were fetched from a single shared bucket per region. That works for curated, vetted extensions but doesn't scale well to user-uploaded code. With endpoint_storage, each endpoint can have its own private set of files, gated by JWT-based access control.
Today's primary use cases:
- User-uploaded extensions. A user uploads a
.sofor their endpoint; the compute downloads it on start. - Per-endpoint config artifacts. Things that need to be associated with one endpoint and accessible from compute_ctl.
Directory layout
endpoint_storage/
├── Cargo.toml # ~750 bytes
└── src/
├── main.rs # binary entry; ~3 KB
├── lib.rs # crate root; ~10 KB
├── app.rs # axum routes; ~22 KB (the bulk)
├── claims.rs # JWT scope checks
└── openapi_spec.ymlAPI surface
endpoint_storage/src/openapi_spec.yml documents the routes. The shape is straightforward:
| Method + path | Purpose |
|---|---|
PUT /<endpoint_id>/<path> |
Upload an object. |
GET /<endpoint_id>/<path> |
Download an object. |
DELETE /<endpoint_id>/<path> |
Remove an object. |
GET /<endpoint_id>/list/... |
List objects under a prefix. |
JWT claims tie each token to a specific endpoint, preventing one endpoint from accessing another's files. The signing keys are managed by the control plane.
Storage backend
Internally, endpoint_storage delegates to libs/remote_storage, the same crate the pageserver uses. So objects can land in S3, Azure Blob, GCS, or a local filesystem (for tests). The translation from "endpoint id + path" to the underlying object key is handled in app.rs.
How compute uses it
compute_tools/src/extension_server.rs is the compute-side downloader. When the spec lists an extension that isn't in the base image, compute_ctl issues a GET against the endpoint_storage URL given in the spec and writes the file into Postgres's lib/ directory before starting Postgres.
Operational notes
The service is stateless and horizontally scalable — adding more replicas behind a load balancer just works as long as they all see the same backing bucket. Auth is fully delegated to JWT verification; no per-endpoint database lookup is on the hot path.
Key source files
| File | Purpose |
|---|---|
endpoint_storage/src/main.rs |
Binary entry. |
endpoint_storage/src/app.rs |
HTTP routes and request handling. |
endpoint_storage/src/claims.rs |
JWT verification + endpoint-id matching. |
endpoint_storage/src/openapi_spec.yml |
OpenAPI definition (linted by make lint-openapi-spec). |
compute_tools/src/extension_server.rs |
Compute-side consumer. |
See also
- compute_ctl / extensions — the consumer.
- Remote storage — the abstraction over S3/GCS/Azure.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.