PostgreSQL
Use node-postgres, Neon, Supabase or Drizzle with the same portable repository.
PostgreSQL is the database for Vercel and for any deployment that needs a managed, shared store. The adapter reuses the same portable SQL repository as D1, translated to the PostgreSQL dialect, so behaviour is identical across backends.
No driver is bundled. You pass a client, which keeps connection pooling and credentials in your hands.
The pool is created on the first query rather than on import, so a build step or a CLI invocation without the variable reports an actionable error instead of failing while the configuration module loads.
Accepted clients
postgres() takes anything with a compatible query surface:
| Client | Shape |
|---|---|
pg Pool / Client | query(text, values) => { rows } |
| Neon serverless driver | the same query shape |
Supabase postgres client | the same query shape |
drizzle(pool) | execute(query) |
Both import paths are the same implementation:
@heyo-sh/heyo-status/db/postgres and
@heyo-sh/heyo-status/deployments/vercel.
Migrations
Through the lazy wrapper this calls PostgresStatusDatabase.migrate(), which
applies the bundled migrations and records them in
__heyo_status_migrations. Run it:
- once per environment before the first deploy, and
- after upgrading the package, as part of your release job.
Request handlers never migrate automatically, so a cold start cannot race schema changes.
Options
migrate: true applies migrations on construction — appropriate for local
and test databases, not for a shared production one.
Connection pooling
Serverless functions and pooled PostgreSQL need care:
- On Vercel, prefer a pooled connection string (PgBouncer, Neon pooler, Supabase pooler). A direct connection per invocation exhausts the server.
- Keep the pool small; a status page issues a handful of queries per request.
- A status page is read-heavy, and
cache.snapshotTtlMsremoves most repeated reads inside one instance.
Operational notes
- Timestamps are stored as epoch milliseconds, exactly as in SQLite and D1, so history is portable between backends.
- A unique index on the subscriber destination is what makes concurrent subscription requests resolve to one row.
heyo-status check runanddb seedwork against PostgreSQL from a developer machine as long asDATABASE_URLis reachable.