docs/deployment/production-database.md
The production database runs on Neon PostgreSQL with Cloudflare Hyperdrive providing connection pooling at the edge.
The connection string format: postgresql://user:pass@host/dbname?sslmode=require
Hyperdrive is provisioned via Terraform. The module in infra/modules/cloudflare/hyperdrive/ parses the Neon connection string and creates a Hyperdrive config with connection pooling:
# Provision Hyperdrive for staging
bun infra:staging:edge:apply
This creates two Hyperdrive bindings per environment:
| Binding | Caching | Use for |
|---|---|---|
HYPERDRIVE_CACHED | Disabled by default | Read-heavy queries (enable in Terraform if needed) |
HYPERDRIVE_DIRECT | None | Writes, real-time reads |
After Terraform applies, copy the Hyperdrive IDs from the output into apps/api/wrangler.jsonc for each environment.
See Database: Connection Architecture for how these bindings are used in application code.
Migrations run directly against Neon (not through Hyperdrive). The db/ workspace provides environment-specific commands:
# Staging
bun db:migrate:staging
# Production
bun db:migrate:prod
These commands read connection strings from .env.staging.local and .env.prod.local respectively. See Database: Migrations for the full workflow.
::: warning
Always review generated migration SQL before running against production. Use bun db:generate to preview changes, then inspect the files in db/migrations/ before applying.
:::