Skip to main content

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

FieldTypeRequiredRules
versionstringnoPostgreSQL 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