Skip to content

Local Postgres

Local Postgres is the fastest dev loop. No network round-trip, no Neon account, and secrets never leave your machine.

The copy from .env.example:

Terminal window
docker run --name sadie-pg \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=sadie \
-p 5432:5432 -d postgres:16

Then in .env.local:

Terminal window
DATABASE_URL=postgres://postgres:postgres@localhost:5432/sadie

Apply the schema:

Terminal window
pnpm db:migrate

That’s it. pnpm dev should now boot and the first request will bootstrap a user + session.

If you already run Postgres locally via Homebrew or apt, create a database and user:

Terminal window
createdb sadie
# or, in psql:
# CREATE DATABASE sadie;

Set DATABASE_URL to match your credentials. Anything that is not a .neon.tech or .neon.build hostname is treated as a standard Postgres endpoint and served by the postgres-js driver.

packages/db/src/client.ts inspects the hostname of DATABASE_URL. Neon hostnames route to the HTTP driver (stateless, edge-friendly). Everything else routes to postgres-js, a pooled TCP driver tuned for long-lived server processes like next dev.

Both drivers expose the same Drizzle query-builder API, so repositories in packages/db/src/repos.ts do not branch on driver.

When the hostname is ambiguous (for example, you proxy a Neon database through db.internal), force the driver explicitly:

Terminal window
SADIE_DB_DRIVER=neon-http # force HTTP, regardless of hostname
SADIE_DB_DRIVER=postgres # force pooled TCP

The override is read once on boot. See packages/db/src/client.tsselectDriver.

For the postgres-js driver, SADIE_DB_POOL_MAX controls the max pool size (default 5). Raise it for load testing; leave the default for normal dev.

Terminal window
SADIE_DB_POOL_MAX=10

Sadie’s schema uses Postgres-only features:

  • pgTable, pgEnum, jsonb, doublePrecision
  • uniqueIndex with composite columns
  • $type<T>() branded JSONB columns (compile-time contract)

A SQLite adapter would require a schema rewrite. It is not on the roadmap. If you want zero-infra development, use the Docker one-liner above. It is genuinely one command.

To wipe and re-seed demo fixtures:

Terminal window
pnpm db:reset

To drop the Docker container entirely:

Terminal window
docker rm -f sadie-pg