PostgreSQL
A postgres service is a PostgreSQL database that AppHaven provisions and
operates for you. You declare it in your manifest; the platform generates its
credentials, manages its storage, and backs it up continuously. Your code just
reads one environment variable.
Declare the database
services:
web:
type: container
build:
dockerfile: Dockerfile
ports:
- 3000
env:
DATABASE_URL: ${service.db.url}
depends_on:
- service: db
condition: healthy
db:
type: postgres
version: "17"
That's the whole setup. On deploy, AppHaven provisions the db service, and
your web container starts with DATABASE_URL set to a ready-to-use
PostgreSQL connection URL.
Fields
| Field | Type | Required | Rules |
|---|---|---|---|
version | string | no | PostgreSQL major version. Supported: "17". Default "17". |
version is the only field you set: a postgres service has no image,
ports, env, volumes, or healthcheck — those are managed by the
platform. Its storage comes from the deployment's overall
storage budget, not a per-database setting. Other services
reach it by name on the internal network (db:5432),
and an app can declare up to four postgres services, for example a main
database and a separate one for a queue.
What the platform takes care of
- Provisioning. AppHaven runs and operates the PostgreSQL instance. You never pick an image or configure the engine.
- Credentials. The database name, user, and password are generated for you and handed to your app when it starts. They never appear in your repository, your manifest, or the console; there is nothing to leak.
- Storage. The database's data lives on the deployment's persistent storage, kept across every redeploy of your app. It draws on the deployment's storage budget, shared with your volumes and backups.
- Backups. The database is continuously backed up, with point-in-time recovery; see Backups & recovery.
- Readiness. The database reports when it is ready to accept connections,
so your app can wait for it with
depends_on(below).
Connection references
Your app receives the connection details through ${...} references in its
env values (or build.args). The references are resolved when your app
starts: the real credentials are never written into your repository or
stored in your manifest.
services:
web:
type: container
build:
dockerfile: Dockerfile
env:
DATABASE_URL: ${service.db.url}
# or compose your own from the parts:
# DATABASE_URL: postgres://${service.db.user}:${service.db.password}@${service.db.host}:${service.db.port}/${service.db.database}
A postgres service exposes the fields url, host, port, user,
password, and database. A reference must name a managed service in the
same manifest and a field it exposes; anything else fails validation before a
deploy is attempted.
Waiting for the database
Referencing ${service.db.url} sets the value, but it does not make your app
wait for the database to be ready. If your app connects at startup and doesn't
retry, declare the dependency explicitly:
web:
depends_on:
- service: db
condition: healthy
If your app retries its own database connection (most frameworks do), you can
skip depends_on and let it start immediately.
Previews get their own database
A preview environment (any deploy of a non-production branch) gets its own database, with its own storage and its own credentials. Experimenting on a branch never touches production data.
Where to go next
- Services: networking and start order.
- Environment variables: configuration and secrets.
- Getting started: deploy your first app.