DEV Community

arian gogani
arian gogani

Posted on Fully Autonomous

I removed the database setup step from my Next.js development workflow

I wanted contributors to clone a small Next.js app and run it without Docker, a local Postgres server, or a cloud database credential. The app is Surka, an early-stage tool for coordinating cross-promotion swaps between founders. The product is still looking for its first real swaps, but the database setup is useful on its own.

The local path

With Node 20 or newer, the quick start is:

npm install
cp .env.example .env.local
# Set ADMIN_PASSWORD and SESSION_SECRET in .env.local
npm run dev
Enter fullscreen mode Exit fullscreen mode

PGlite runs Postgres in WebAssembly and stores local data in ./.pglite. The app applies its migrations when it opens the local database. No separate database process or connection string is needed.

One schema, two drivers

The Drizzle schema and SQL migrations live in one place. The database client selects PGlite for local work when DATABASE_URL is absent, and a Postgres driver for the hosted database when it is present. Production currently uses Neon. The switch is in src/db/client.ts.

This arrangement reduces one kind of drift: I do not maintain a SQLite development schema and a Postgres production schema. It does not prove both drivers behave identically, so the integration tests still matter.

What the tests buy me

The integration tests use an in-memory PGlite database and run the actual migrations. They exercise real Postgres constraints and service transactions instead of replacing persistence with a mock. A mock that simply records a call cannot tell me whether a foreign key, uniqueness rule, or transaction boundary behaves as intended. I am not claiming this has already caught a particular production incident.

The rest of the app follows the same preference for simple boundaries: forms use server actions and work without client-side JavaScript; the rules for swaps and reputation are plain functions; the service layer records state changes in a timeline.

The tradeoff is real. PGlite still has startup and migration cost, and tests against it do not replace tests against the exact hosted driver or a deployed smoke test. For this small app, removing a service dependency from first-run setup was worth it.

The code is AGPL-3.0: https://github.com/arian-gogani/surka

Try the live Surka demo. It is an early-stage product, with no completed real-world swaps yet.

I would be interested in cases where this local-PGlite / hosted-Postgres split surprised you.

Top comments (0)