Database hosting
Run Voltro on any hosted Postgres, MySQL, MariaDB, or SQL Server — Supabase, Neon, Vercel Postgres, Railway, Render, Fly.io, AWS RDS, PlanetScale, Azure SQL, and more. Connection strings, pooling, gotchas.
Voltro runs on five SQL backends — postgres, mysql 8+, mariadb 10.6+, mssql 2019+, and sqlite (local file) — plus the beta Turso dialect (the Rust SQLite rewrite, local file or :memory:). Any managed database that speaks one of those dialects works. You set two environment variables — DB_DIALECT and DB_URL — and the framework's schema, queries, workflows, and reactive engine run unchanged.
This page maps the common hosted-database providers to the Voltro dialect they back, the connection shape, and the gotchas worth knowing before you deploy. Each provider has its own page below.
The two-variable contract
DB_DIALECT=postgres # postgres | mysql | mariadb | mssql | sqlite
DB_URL=postgresql://user:pass@host:5432/db?sslmode=requireDB_DIALECT picks the driver; DB_URL is the connection string for the provider. When a single URL doesn't fit, the discrete DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_DATABASE fields are the dialect-agnostic alternative (and PG_HOST / PG_PORT / PG_USER / PG_PASSWORD / PG_DATABASE are accepted as a fallback). Env always wins over app.config.ts's store: field.
Declare your dialect's driver
Each app declares the driver package for its DB dialect as a dependency — the CLI does not bundle every driver, so a production image only ships the one your app actually uses (a memory-store app ships none, and never pulls e.g. turso's ~90 MB native binary):
| Dialect | Driver package |
|---|---|
postgres |
@voltro/sql-postgres |
mysql / mariadb |
@voltro/sql-mysql |
mssql |
@voltro/sql-mssql |
sqlite |
@voltro/sql-sqlite |
turso |
@voltro/sql-turso |
pnpm add @voltro/sql-postgres # in the app that uses store: 'postgres'Scaffolded projects already declare the right driver, and voltro add mssql adds @voltro/sql-mssql for you. If a driver is missing at boot, voltro serve fails with a message naming the exact package to install — it never silently falls back. A store: 'memory' app needs no driver.
Providers at a glance
| Provider | Voltro dialect | Pooling | Notes |
|---|---|---|---|
| Supabase | postgres | Supavisor (:6543 txn / :5432 session) |
LISTEN/NOTIFY needs the session port or a direct connection; the transaction pooler drops it. |
| Neon | postgres | PgBouncer (-pooler endpoint) |
Serverless functions use the pooled endpoint; CDC listener uses the direct endpoint. Branching for preview DBs. |
| Vercel Postgres | postgres | Neon-backed pooler | Neon under the hood. Same pooled-vs-direct split as Neon. |
| Railway | postgres / mysql | none by default | Plain managed Postgres or MySQL. Use the private network URL in-cluster. |
| Render | postgres | none by default | Internal vs external connection strings; internal avoids egress + SSL friction. |
| Fly.io Postgres | postgres | none (or pgbouncer app) | Unmanaged Postgres app — you own backups + HA. Flycast for internal routing. |
| AWS RDS / Aurora | postgres / mysql / mariadb | RDS Proxy (optional) | Full LISTEN/NOTIFY on Postgres (direct endpoint for the CDC listener). MariaDB adds binlog CDC; needs a binlog-enabled parameter group. |
| DigitalOcean | postgres / mysql | built-in connection pool | Pooler in transaction mode drops LISTEN/NOTIFY — add a direct connection for CDC. |
| Timescale | postgres | none by default | Postgres + the TimescaleDB extension. Full reactive surface; hypertables are opt-in per table. |
| CockroachDB | postgres (wire) | built-in | Caveat: wire-compatible, NOT feature-compatible. No LISTEN/NOTIFY → no native CDC. Cross-instance reactivity still works via @voltro/plugin-broadcast (Redis / NATS fan-out of app-mutation changes). May not pass all of Voltro's pg DDL. SQL surface only. |
| PlanetScale | mysql | built-in (Vitess) | Caveats: no native CDC (mysql is inline-only; no binlog access on Vitess) → use @voltro/plugin-broadcast for cross-instance reactivity. Vitess also disables foreign keys by default — enable FK support on the branch or reference() cascades won't apply. |
| Azure SQL | mssql | none by default | SQL Server 2019+ surface. CDC is inline-only (no native cross-instance feed) — add @voltro/plugin-broadcast for cross-instance reactivity. OUTPUT INSERTED instead of RETURNING; encrypted connection required. |
| Turso | turso (local file) | in-process MVCC pool | Supported (beta) via @voltro/sql-turso — the Rust SQLite rewrite with MVCC concurrent writes (BEGIN CONCURRENT). Embedded engine: a local file or :memory:, NOT a hosted provider. Remote libSQL / Turso Cloud (libsql://…) is still rejected — that's a libSQL-client concern, not this dialect. |
Legend: the dialect column is the value you set for DB_DIALECT. "Pooling" is the connection-pooler the provider ships; it matters because the native Postgres reactive path (LISTEN/NOTIFY CDC) needs a long-lived session-mode connection — transaction-mode poolers silently break it (the broadcast plugin sidesteps that, see below).
The one cross-cutting gotcha: pooling vs LISTEN/NOTIFY
On Postgres, Voltro's low-latency native reactive path uses LISTEN/NOTIFY. That needs a long-lived, session-mode connection. A transaction-mode pooler (Supabase Supavisor :6543, Neon's pooled endpoint, DigitalOcean's transaction pool, RDS Proxy without pinning) hands you a fresh backend per transaction — the LISTEN is registered on a connection you never see again, so change events never arrive.
You have two ways to fix it — pick by what you need:
Keep native CDC — query the CDC listener to a direct / session-mode connection while application queries keep going through the pool. Each provider page below spells out the exact endpoints. This preserves the full Postgres path: low-latency fan-out and capture of out-of-band writes (a
psqlsession, another service touching the DB).Skip the listener with
@voltro/plugin-broadcast— a Redis / NATS pub/sub bus that fans every committedctx.storemutation out to all replicas. It opens noLISTENconnection, so it works straight through the transaction pooler — and it's the same plugin you'd add for cross-replica reactivity on a multi-pod deployment anyway. Trade-off: the bus carries app-mutation changes, not out-of-band DB writes — only the nativeLISTEN/NOTIFYpath observes those.
MySQL / MSSQL don't have the pooling concern at all — their change path is inline (single-instance) and, for cross-replica fan-out, rides the broadcast plugin. MariaDB adds native binlog CDC (not connection-pinned). SQLite is in-process. See Multi-replica reactivity for the full tier breakdown.
What the dialect page covers vs what these pages cover
These provider pages are about getting connected — the connection string, SSL, pooling, and provider-specific quirks. For the deep dialect surface — RETURNING gaps, CDC mechanics, cluster workflow locks, read-replica routing, JSON handling, identifier quoting — see the underlying SQL dialects section. Every provider page links to its dialect page.