Why Databases Were Always the Friction Point
Every time I spun up a new project, the database was the thing that slowed everything down. Provisioning an RDS instance, waiting for it to boot, managing connection pools, paying for idle compute it never felt right for the way I actually build.
Then I started using Neon.
What Neon Actually Is
Neon is serverless Postgres. Not "serverless" as marketing speak literally serverless: compute scales to zero when idle, spins back up in milliseconds, and you pay only for what you use.
Under the hood, Neon separates storage and compute, which unlocks something that traditional databases can't do: database branching.
Database Branching The Game Changer
This is the feature that made everything click for me.
With Neon, every branch of my Git repo can have a corresponding database branch a full copy of the schema and data, isolated, instant, and free to create.
# Create a branch for a feature
neonctl branches create --name feature/new-billing-model --project-id <id>
The branch forks from the parent in seconds, regardless of database size, because Neon uses copy-on-write at the storage layer.
What This Enables
- Safe migrations: Run
drizzle-kit pushon a branch, verify it's correct, then merge - PR previews with real data: Each Vercel preview deployment connects to its own DB branch
- Zero fear of schema changes: Roll back by just deleting the branch
Before Neon, schema changes were my most stressful deploys. Now they're a non-event.
How My Workflow Looks
Local Development
I keep a dev branch in Neon for local work. My .env.local points directly to Neon — no local Postgres, no Docker containers.
DATABASE_URL=postgres://user:pass@ep-xxx.eu-central-1.aws.neon.tech/neondb?sslmode=require
Connection pooling goes through PgBouncer, which Neon provides as a built-in pooled endpoint. I never manage connection limits manually.
ORM: Drizzle + Neon HTTP Driver
For serverless environments (Vercel Edge, Cloudflare Workers), I use the Neon HTTP driver with Drizzle:
import { neon } from "@neondatabase/serverless";
import { drizzle } from "drizzle-orm/neon-http";
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql);
This runs Postgres queries over HTTP no persistent TCP connections, which matters on edge runtimes where cold starts are real.
For Node.js environments (API routes, background jobs), I switch to the WebSocket driver for full Postgres protocol support:
import { Pool } from "@neondatabase/serverless";
import { drizzle } from "drizzle-orm/neon-serverless";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export const db = drizzle(pool);
Migrations
I use Drizzle Kit for schema management. My migration flow:
# Generate migration from schema changes
drizzle-kit generate
# Push to a Neon branch first
DATABASE_URL=$BRANCH_URL drizzle-kit push
# Once verified, push to main
drizzle-kit push
The branch acts as a staging layer. If the migration causes issues, I drop the branch and fix the schema — main is never touched.
Vercel + Neon Integration
Neon has a first-class Vercel integration. When I connect my project:
- Every Vercel preview deployment automatically gets a corresponding Neon database branch
- The
DATABASE_URLenvironment variable is injected per-deployment - Branches are cleaned up when PRs close
This means a PR that adds a new table can be reviewed with real data in isolation the reviewer can open the preview URL and the schema is already migrated on that branch.
Performance Profile
Neon's cold start is under 500ms acceptable for most workloads. For latency-sensitive paths, I keep compute warm by enabling the "Always-on compute" option on production branches.
Scenario Latency
──────────────────────────────────────
Warm query (simple SELECT) ~5ms
Cold start + query ~400ms
Pooled connection query ~3ms
For anything user-facing, I use the pooled endpoint. Cold starts are only relevant for cron jobs and background tasks.
The Cost Model
For solo projects and early-stage SaaS, Neon's free tier is genuinely useful:
- 0.5 GB storage
- 190 compute hours/month
- Unlimited branches
I run three side projects entirely on the free tier. The compute-to-zero behavior means idle projects cost nothing.
What I'd Tell Past Me
- Stop running local Postgres: The Neon dev branch is more reliable and mirrors production exactly
- Branch early, branch often: Treat DB branches like Git branches cheap to create, invaluable when something breaks
- Use the HTTP driver on edge: Trying to use a standard PG driver on Vercel Edge will cause you pain
Final Thoughts
Neon removed the last piece of friction in my serverless stack. Combined with Vercel for hosting and Drizzle for type-safe queries, the entire data layer is now as easy to work with as the frontend.
The architecture-first approach means choosing tools that stay out of your way. Neon does that.
Curious about the full stack I use for client projects? Book a strategy call and I'll walk through the architecture end to end.
