Voltro + Vercel Postgres

Connect Voltro to Vercel Postgres (Neon-backed) — POSTGRES_URL vs the pooled URL, sslmode=require, LISTEN/NOTIFY reactivity, and the serverless pooling caveat.

Vercel Postgres is Neon under the hood, so it uses Voltro's postgres dialect with the full reactive surface — LISTEN/NOTIFY CDC, advisory-lock cluster workflows, read replicas, JSONB. Everything that's true of Neon applies here; Vercel just rebrands the connection strings as env vars.

Connect

Vercel's integration injects a set of POSTGRES_* env vars. Two matter for Voltro:

# Pooled connection (the default POSTGRES_URL — PgBouncer, transaction
# mode). For serverless functions. ⚠ Does NOT support LISTEN/NOTIFY.
DB_DIALECT=postgres
DB_URL=postgresql://[USER]:[PASSWORD]@[ENDPOINT]-pooler.[REGION].postgres.vercel-storage.com/[DB]?sslmode=require
# Direct connection (POSTGRES_URL_NON_POOLING) — session connection,
# supports LISTEN/NOTIFY. Use for long-running processes / the CDC listener.
DB_DIALECT=postgres
DB_URL=postgresql://[USER]:[PASSWORD]@[ENDPOINT].[REGION].postgres.vercel-storage.com/[DB]?sslmode=require

Map POSTGRES_URL_NON_POOLINGDB_URL when you want reactivity; map the pooled POSTGRES_URL only for serverless query traffic. sslmode=require is mandatory.

Enabling CDC

Voltro's change-data-capture is LISTEN/NOTIFY, on by default (CDC=1). On Vercel Postgres the one requirement is to map POSTGRES_URL_NON_POOLINGDB_URL (or at least to query the CDC listener there) — that's the direct, session-mode endpoint. The default POSTGRES_URL is the pooled, transaction-mode endpoint and breaks LISTEN/NOTIFY (below).

Identical to Neon: the pooled (-pooler) endpoint runs transaction-mode PgBouncer and breaks LISTEN/NOTIFY. The reactive engine needs a long-lived session connection.

  • Long-running container → use POSTGRES_URL_NON_POOLING as DB_URL. Reactivity works.
  • Vercel serverless functions → the function lifecycle is per-request; a push-reactive Voltro process wants to stay alive. If you deploy the API as a long-running service (not a serverless function), point it at the non-pooling URL. If you must run serverless, use the pooled URL with CDC=0 (inline-emit only).

Because Vercel Postgres is Neon under the hood, its compute autosuspends when idle — the same warm-keeping + reconnect behavior described on the Neon page applies to the long-lived CDC listener here.

Verify

[voltro:dev] sql dialect resolved: postgres — CDC: LISTEN/NOTIFY, RETURNING: native
[voltro:dev] read replicas: 0 configured (DB_REPLICA_URLS empty) — all queries → primary
[voltro:dev] workflow engine: cluster-sql, dialect=postgres

Confirm with voltro logs --tail 50. Subscriptions that snapshot but never update mean you're on the pooled URL — switch to POSTGRES_URL_NON_POOLING.

See also

  • Neon — the engine behind Vercel Postgres; branching + the same pooled/direct split.
  • Postgres dialect — LISTEN/NOTIFY internals, workflows, replicas, JSONB.