neondatabase/neon
Proxy
The Neon proxy is a TLS-terminating Postgres protocol proxy that sits in front of compute nodes. It authenticates clients, routes them to the right project, and exposes Postgres through three different surfaces: native libpq over TCP, libpq tunneled over WebSockets, and SQL over HTTP. A separate "auth/REST broker" mode adds JWT-aware row-level access for serverless workloads.
The canonical operator-facing documentation is proxy/README.md. The summary below covers what's where in the code.
Surfaces
| Surface | Use case |
|---|---|
| libpq over TCP | Standard psql / drivers. SNI on the TLS handshake selects the project. |
| libpq over WebSockets | Browser environments that can't open arbitrary TCP. Implemented as one-shot WebSocket-tunneled libpq via neondatabase/serverless. |
SQL over HTTP (POST /sql) |
One round-trip query for edge runtimes like Cloudflare Workers or Vercel Edge. JSON in, JSON out. |
| REST broker | JWT-authorized PostgREST-style row access. Optional, gated by --features rest_broker. |
All four are served by the same proxy binary, configured via CLI flags.
Auth backends
proxy/src/auth/ implements multiple authentication strategies. Choose one with --auth-backend:
| Backend | Source of truth | Used in |
|---|---|---|
console |
Production console API; SCRAM with cached secrets | Cloud production |
postgres |
A local Postgres role table | Local development and integration tests |
web / link |
Email login link | Onboarding flows |
local |
Static config file (local_proxy.json) for JWT validation |
local_proxy binary, REST broker |
Directory layout
proxy/
├── Cargo.toml
├── README.md
└── src/
├── lib.rs
├── bin/ # binaries: `proxy`, `local_proxy`
├── binary/ # binary-format helpers
├── config.rs # CLI / config struct
├── auth/ # auth backends (console, postgres, web, ...)
│ └── …
├── pglb/ # the postgres listener-balancer
├── proxy/ # the core libpq proxy state machine
├── serverless/ # SQL-over-HTTP and REST broker
├── http/ # HTTP server scaffolding
├── pqproto.rs # libpq protocol parser/serializer
├── protocol2.rs # newer protocol abstractions
├── stream.rs # TLS / plain socket abstraction
├── cache/ # secret + project cache
├── compute/ # connection to compute (target side)
├── compute_ctl/ # talks to compute_ctl HTTP API
├── control_plane/ # talks to console API (project metadata)
├── cancellation.rs # query cancellation routing
├── rate_limiter/ # per-IP / per-project / per-endpoint
├── redis/ # Redis client for distributed cancellation, secrets
├── sasl/ # SASL framing
├── scram/ # SCRAM-SHA-256 implementation
├── tls/ # certificate loading, SNI extraction
├── console_redirect_proxy.rs # passwordless 'web' login flow
├── batch.rs # batched HTTP req handling
├── intern.rs # string interning for hot-path identifiers
├── waiters.rs # waiter combinator for cross-task signals
├── usage_metrics.rs # billing / consumption telemetry
├── metrics.rs
└── logging.rsConnection lifecycle (libpq)
sequenceDiagram
participant C as Client
participant Proxy as proxy
participant CP as Console API
participant Compute as Compute (postgres)
C->>Proxy: TLS ClientHello (SNI=project.neon.tech)
Proxy->>Proxy: parse SNI → project_id
Proxy->>CP: lookup project, role secrets
CP-->>Proxy: SCRAM secrets, allowed IPs
Proxy->>C: TLS established + Postgres startup
C->>Proxy: SCRAM auth exchange
Proxy->>C: AuthOk
Proxy->>Compute: open libpq connection (start compute if needed)
par bidirectional pipe
Proxy-->>Compute: forward queries
Compute-->>Proxy: forward results
endThe proxy maintains caches (proxy/src/cache/) for project metadata, SCRAM secrets, and per-project IP allowlists so the hot path doesn't hit the console API on every connection. Cache invalidation flows through Redis pub/sub (proxy/src/redis/).
When the requested compute is suspended, the proxy issues a "wake compute" call via the compute_ctl HTTP API and waits — see proxy/src/compute_ctl/.
SQL over HTTP
proxy/src/serverless/ implements POST /sql. Design choices documented in proxy/README.md:
- Uses Postgres extended query protocol but in text format to avoid client-side binary-decoding work and dodge known driver bugs (sfackler/rust-postgres#1030).
- Maps Postgres types to JSON best-effort: numbers, booleans, arrays, jsonb stay as JSON; types without a JSON equivalent become strings.
- Mimics node-postgres' response shape (column oids, command tag) to ease integration with JS libs.
Optional headers tweak the response:
Neon-Raw-Text-Output: true— skip type conversion.Neon-Array-Mode: true— return rows as arrays not objects.
Query cancellation
Cancellation requests are routed via Redis (proxy/src/cancellation.rs, proxy/src/redis/). When a client opens a connection, the proxy stores (cancellation_key → backend_address) in Redis. A subsequent CancelRequest from any proxy instance can then forward to the right backend, regardless of which proxy holds the original connection.
Local testing
proxy/README.md walks through running a local Postgres + proxy + Redis stack. The "auth broker setup" section documents JWT-validating mode used by Vercel/Cloudflare integrations.
Rate limiting
proxy/src/rate_limiter/ has multi-tier rate limiting:
- Per source IP.
- Per project.
- Per endpoint (a project can have multiple endpoints).
- Connection rate vs. query rate.
Limits are configurable via flags.
Key source files
| File | Purpose |
|---|---|
proxy/src/bin/proxy.rs |
Main binary entry. |
proxy/src/bin/local_proxy.rs |
Local-dev variant. |
proxy/src/proxy/ |
Core libpq proxy state machine. |
proxy/src/serverless/ |
SQL-over-HTTP implementation. |
proxy/src/auth/ |
Auth backends. |
proxy/src/scram/ |
SCRAM-SHA-256. |
proxy/src/tls/ |
TLS termination, SNI parsing. |
proxy/src/control_plane/ |
Console API client. |
proxy/src/cancellation.rs |
Cross-instance cancellation. |
proxy/src/redis/ |
Redis pub/sub for cache invalidation, cancellation. |
proxy/src/usage_metrics.rs |
Billing telemetry. |
proxy/README.md |
Operator-facing user guide. |
Related supporting crates
libs/proxy/ holds:
postgres-protocol2/andtokio-postgres2/— forks of the rust-postgres protocol crates with proxy-specific changes (text-format extended queries, type response handling).postgres-types2/— types matching the proxy's protocol fork.subzero_core/— stub for the optional REST broker (real implementation is gated behind--features rest_broker).json/— proxy-specific JSON serialization helpers.
See also
- Compute_ctl — proxy talks to compute_ctl when waking a suspended compute.
- Proxy HTTP API — SQL over HTTP request/response shape.
proxy/README.md— the canonical operator guide.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.