SysPad › Lessons › database lessons › Neon Postgres
How Neon Postgres works
Serverless Postgres - scale-to-zero, branching, built-in connection pooling. Compute-unit sized; the free tier resumes from zero in ~500ms, which your p99 will notice.
What if Postgres worked like Git? Neon separates storage from compute, which unlocks two tricks classic databases cannot do: branch a full database for every pull request in seconds, and scale compute to zero when nobody is querying. (It is also the database behind SysPad's own backend.)
What you will learn
- What does separating storage from compute make possible?
- How does database branching change dev/test workflows?
- What does scale-to-zero cost you, and when is that fine?
- Why does serverless need Neon's built-in pooler?
Storage apart from compute
Classic Postgres welds disk and CPU into one box. Neon keeps data in a versioned storage layer and runs stateless Postgres compute units (CU ≈ 1 vCPU / 4GB) against it: compute can grow, shrink, sleep, or multiply without touching the data.
A database per pull request
Because storage is versioned, a branch is copy-on-write: instant, and it only stores what diverges. Every PR can get a real database with production-shaped data; test destructive migrations, then delete the branch. This replaces the shared, perpetually-broken staging DB.
⚓ SysPad uses exactly this: the backend's migrations get rehearsed on a branch before they touch main. Dogfooding, verified.
Scale-to-zero and its price
Idle compute suspends: you pay storage only. The first query after a suspend pays a ~half-second resume. For side projects, dashboards, and dev branches that is free money; for a latency-sensitive API it is a p99 landmine, so paid plans let you keep compute warm.
Why do serverless functions and Postgres traditionally fight?
Each function instance opens its own connection; Postgres tolerates a few hundred. A traffic spike of 2,000 concurrent lambdas is a connection storm. Neon ships a pooler (PgBouncer-style) on a separate endpoint: functions connect to the pooler, the pooler multiplexes onto a handful of real connections. Use the pooled connection string from serverless, the direct one for migrations.
Flashcards
- Your team's shared staging database is always broken by someone's half-run migration. What is the Neon-shaped fix?
- Ephemeral branches: each PR/CI run branches main (copy-on-write, seconds), runs its migrations and tests in isolation, and is deleted. Staging stops being shared mutable state.
- A production API on Neon free tier shows a clean p50 but a brutal p99 spike every morning. What is happening?
- Overnight idle suspends compute; the first queries pay the ~500ms resume. Either accept it (internal tools), or move to a plan/config that keeps compute warm for user-facing paths.
- Lambda handlers get "too many connections" from Neon under load, though each opens just one connection. Diagnosis and fix?
- A thousand concurrent lambdas is a thousand connections: the classic serverless storm. Point them at Neon's pooled endpoint (built-in PgBouncer) and keep the direct endpoint for migrations.
Sources
- Neon architecture (storage/compute separation)
- Branching
- Autoscaling and scale to zero
- Connection pooling
Open the SysPad canvas · Official Neon Postgres documentation