codexmachina
Component

Every verified stack that runs on Serverless (Vercel / Lambda).

Serverless functions: many short-lived instances, one DB connection each, behind Neon's pooler.

0 verified stacksHow we verify →

0 verified stacks

No verified stacks published yet.

What Serverless (Vercel / Lambda) gives you

This client is sized for a runtime where the platform, not the process, decides concurrency. Vercel functions and Lambda run many short-lived instances, each serving one request or a handful before freezing, and whatever pool an instance opens gets multiplied by however many instances the platform chose to spin up. So `dbClient` emits `postgres(process.env.DATABASE_URL!, { prepare: false, max: 1 })` — one backend per instance — and leaves the multiplexing to Neon's PgBouncer endpoint, which is the only layer that can see across processes. The MySQL branch makes the same bet with `mysql2`'s knob: `mysql.createPool({ uri: process.env.DATABASE_URL!, connectionLimit: 2 })`. Each is then bound to Drizzle (`drizzle(sql)` over `drizzle-orm/postgres-js`, `drizzle({ client: pool })` over `drizzle-orm/mysql2`) and exported as `db`, alongside the raw `sql` / `pool`.

The failure this avoids is connection exhaustion, and its nastiness is that it is a load failure rather than a compile failure. A `max: 10` pool behaves perfectly in local dev and in a single smoke-test request; the first time traffic fans out it becomes ten times the instance count, Postgres starts refusing connections at `max_connections`, and the code that caused it still reads fine in review. Driver-side pooling is simply the wrong tool at this shape — one connection per instance plus a real pooler is. `prepare: false` is the second half of the same decision. `DATABASE_URL` here is Neon's pooled `-pooler` host, meaning PgBouncer in transaction mode, which hands a different backend to each transaction; a statement prepared on one is missing on the next.

The same property rules out everything else that assumes a stable session — `LISTEN`/`NOTIFY`, session-scoped `SET`, advisory-lock sessions, server-side cursors, `WITH HOLD`. Those paths need Neon's direct endpoint, and only those paths.

Built for

Fan out across instances without exhausting Postgres

`max: 1` in the emitted `postgres()` call caps each function instance at a single backend, so total connections track the pooler's ceiling rather than instance count multiplied by pool size.

Run against a transaction-mode pooler

`prepare: false` turns off prepared statements, which do not survive an endpoint that may hand each transaction a different backend — the default that silently breaks the moment the app is pointed at the `-pooler` host.

Keep a MySQL function's footprint small

The `mysql2` branch creates a pool of two (`connectionLimit: 2`) — not the ten a persistent process would take — so the same fan-out arithmetic that governs the Postgres branch stays bounded on MySQL.

Drop below the ORM for raw SQL

`export const sql` is the configured `postgres` tagged template itself (`pool` in the MySQL branch), so one-off queries and migration scripts run through exactly the connection settings Drizzle's `db` uses, not a second ad-hoc client.

Point one env var at the right Neon endpoint

`DATABASE_URL` is documented as the pooled `-pooler` string, which is what makes `max: 1` and `prepare: false` correct together; the direct endpoint stays reserved for the session-scoped work transaction mode forbids.

Why Serverless (Vercel / Lambda), specifically

note

max: 1 per instance + Neon's pooler is the rule — a large max times serverless fan-out exhausts Postgres connections.

note

prepare: false — Neon's pooled endpoint is PgBouncer transaction mode (prepared statements break).

note

Transaction mode forbids anything that spans transactions on one backend: LISTEN/NOTIFY, session-scoped SET, advisory-lock sessions, server-side cursors, WITH HOLD. Use Neon's direct (non-pooled) endpoint for those paths only.

note

Keep idle_timeout ~20s / connect_timeout ~10s so frozen instances release backends fast; lean on PgBouncer, never on driver pooling, to stay under the project's max_connections.

What Serverless (Vercel / Lambda) pulls in

bun add postgres drizzle-orm
DATABASE_URLNeon POOLED (-pooler) connection string