Database connection
The API talks to Supabase Postgres with the pg driver. Runtime traffic uses DATABASE_URL. Schema changes are SQL files under supabase/migrations/ and are applied separately with the Supabase CLI.
Runtime connection
DATABASE_URL is validated as an absolute PostgreSQL URL during configuration loading. createDatabase() opens one connection pool and exposes a small lifecycle boundary:
connect()checks the pool withSELECT 1;disconnect()closes the pool;query()andtransaction()are available to infrastructure adapters inside feature slices.
The HTTP runtime connects to the database, confirms the realtime publisher, and only then opens the listener. A failed connection closes the application and telemetry resources, then prevents the API from accepting traffic.
On shutdown, the runtime closes Fastify first, then the SQS client, disconnects the database, shuts down analytics, and shuts telemetry down last. Broadcast publishes are individual requests, so there is no notification-bus connection to close. Repeated shutdown requests share the same close operation. See Realtime event channels for that publisher.
Administrative connection
Supabase CLI migration commands use DIRECT_URL when a direct, non-pooler connection is required. The API does not read DIRECT_URL. See Manage database migrations for the operational flow, Core user and media schema for identity and media tables, and Booking persistence schema for booking tables.
Boundary with feature slices
Application use cases do not import pg. A feature declares a persistence port in its domain layer, and an infrastructure adapter uses the shared client to implement that port. Raw database rows must not escape into application or contract types.
Driver and Data API boundary
pg is the only runtime database driver. Every SQL query enters through Fastify and the shared pool. Browsers and Telegram apps do not query Postgres.
PostgREST (the Supabase Data API) stays disabled. @supabase/supabase-js is an HTTP client for that API, so it is not a query path and is not used for database access. The supabase package in the API is the CLI for migrations under supabase/migrations/.
Core tables follow the same model: application commands own authorization, and there is no direct browser access. See Core user and media schema for that boundary and for transactional writes such as media finalization.