ByteBite Docs
Infrastructure

Database

PostgreSQL staging service, migrations, seeds, and tenant-domain schema.

Database

ByteBite uses PostgreSQL as the sole primary database, accessed through Drizzle ORM in packages/db.

Staging PostgreSQL

AttributeValue
EnginePostgreSQL 18
ManagementDokploy PostgreSQL service
Imagepostgres:18
Display name (observed)bytebite-staging-postgres
Generated hostname (example)bytebite-staging-postgres-vmg94p
Database namebytebite
Userbytebite
Port5432 (internal Docker network only)
Public port 5432CLOSED (verified 2026-09-08)

Generated hostnames are Dokploy-runtime identifiers — not permanent.

Connection

The API receives DATABASE_URL through Dokploy environment configuration. The connection string contains credentials and must never appear in documentation or Git.

Local development uses a separate PostgreSQL instance (postgres:17-alpine in compose.yml, published on 127.0.0.1:5432).

Drizzle and migrations

ComponentLocation
Schemapackages/db/src/schema/
SQL migrationspackages/db/migrations/
Migration runnerpackages/db/src/migrate.ts → bundled as db/dist/migrate.js
Drizzle configpackages/db/drizzle.config.ts

Migrations are explicit — the API does not auto-migrate on startup.

Running migrations (staging)

Inside the api container:

node db/dist/migrate.js

From a machine with staging DATABASE_URL:

pnpm deploy:db:migrate

Run after each deploy that includes schema changes.

Staging seeds

Staging tenant seeds are separate from local dev seeds:

CommandHostnamesWhen
node db/dist/seed-staging.jsluigi.staging.getbytebite.co, mario.staging.getbytebite.coFresh staging DB, once
pnpm db:seed (local only)luigi.bytebite.test, mario.bytebite.testLocal dev

Never run seed-staging.js against production. Never run it against the local dev database (it overwrites domain hostnames for shared row IDs).

Implementation: packages/db/seeds/staging.ts.

Infrastructure-relevant schema

restaurants

Stores restaurant identity, status (ACTIVE / INACTIVE), and branding.

restaurant_domains

Maps normalized hostnames to restaurants. Tenant resolution is an exact match on hostname after normalization.

ColumnInfrastructure relevance
hostnameUnique, normalized — the tenant lookup key
typeBYTEBITE_SUBDOMAIN or CUSTOM_DOMAIN
is_primaryAt most one primary per restaurant
verified_atRequired for custom domains (future)

DNS wildcard existence does not create rows here. Unknown hostnames fail tenant lookup.

Failure expectations

ConditionAPI behavior
Unknown/inactive tenantHTTP 404 (Restaurant not found) on tenant-aware routes
Database unreachableHTTP 503 on tenant-aware routes
/healthAlways available (no tenant lookup)
/health/dbReturns degraded if DB unreachable

Backups

Off-host PostgreSQL backup and restore strategy is not established. Local Traefik configuration snapshots exist on the APP VM but do not cover database data. See Backups and Known gaps.

On this page