Managed Postgres

Managed Postgres on Lizard is a PostgreSQL database that you add to a project with lizard add postgres. New databases run PostgreSQL 18 by default. Lizard stores the connection string in DATABASE_URL and its parts in PGHOST, PGPORT, PGUSER, PGPASSWORD and PGDATABASE. Connect services with a reference such as ${{postgres.DATABASE_PRIVATE_URL}}. The database uses the same CPU, memory and storage rates as apps. You can query it in the dashboard’s SQL editor. For an overview and prices, see the Managed Postgres page.

Provision

lizard add postgres

The first Postgres addon is named postgres, so ${{postgres.DATABASE_URL}} works immediately.

Environment variables

The addon exposes a standard set of connection variables:

VariableDescription
DATABASE_URLFull connection string over the public endpoint (postgresql://…)
DATABASE_PRIVATE_URLConnection string over the project’s private network (<name>.lizard.internal:5432)
PGHOSTHost
PGPORTPort
PGUSERUser
PGPASSWORDPassword
PGDATABASEDatabase name
POSTGRES_USERAlias for the user
POSTGRES_DBAlias for the database
POSTGRES_PASSWORDAlias for the password

Postgres connection string

Each database has two connection strings. Both use the user postgres and the database postgres:

VariableUse it fromFormat
DATABASE_PRIVATE_URLServices in the same projectpostgresql://postgres:<password>@<name>.lizard.internal:5432/postgres
DATABASE_URLYour machine, CI, or a service in another projectpostgresql://postgres:<password>@<host>:<port>/postgres

<name> is the database’s name in the project, postgres for the first one. Lizard assigns the public host and port when it creates the database, so read them from DATABASE_URL, PGHOST and PGPORT rather than typing them. The private address works only inside the project; see private networking.

Most drivers take the string as is:

// Node.js with pg
import pg from 'pg';
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
# Python with psycopg
import os, psycopg
conn = psycopg.connect(os.environ["DATABASE_URL"])

psql and other libpq tools read the PG* variables, so they connect with no arguments.

How do I see the connection string?

  • Dashboard: open the database in your project. The Overview tab shows DATABASE_URL and the private URL with copy buttons. The Secrets tab lists every connection variable and the ${{…}} reference to paste into a service.
  • CLI: lizard run --service postgres -- printenv DATABASE_URL prints the public string. It contains the password, so do not paste it into logs or chat.

The string is a credential. Point services at it with a reference instead of copying it into a secret, so they get the current value on every deploy.

Connect a service

Reference the private connection string from the consumer service and redeploy:

lizard secrets set DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' --service api
lizard redeploy --service api

The reference resolves at deploy time, so every consumer picks up the addon’s current values on its next deploy. Use DATABASE_URL instead for clients outside the project. Every service in the project also gets the addon’s public DATABASE_URL at the lowest precedence; an explicit reference overrides it.

Verify connectivity from your machine without printing the connection string:

lizard run --service postgres -- sh -c 'psql "$DATABASE_URL" -c "SELECT 1"'

lizard run --service postgres runs the command on your machine with the database’s public connection values, so it needs psql installed locally. lizard run --service api would pass ${{…}} references through as literal text; see lizard run.

Run migrations on deploy

Use a pre-deploy command for migrations. It runs only when a start command is also set, as sh -c "<pre> && exec <start>" at the start of every container: each replica, each restart. Make migrations safe to run many times and at the same time, and compatible with both the old and new application version:

lizard service set api --set preDeployCommand="npm run migrate" --set startCommand="npm start"
lizard redeploy --service api

For a Django app the command is python manage.py migrate; see the Django guide and Python app hosting. The Umami and Flowise guides show complete apps on Managed Postgres.

Browse and query data

Open the Postgres editor in the dashboard (lizard open) to run SQL and browse tables directly. For ad-hoc local work, run a command with the addon’s connection values:

lizard run --service postgres -- sh -c 'exec psql "$DATABASE_URL"'

Grow storage

Data volumes are grow-only:

lizard scale --service postgres --storage 8192

Multiple databases

Adding a second Postgres gives it a generated name (e.g. postgres-autumn-bear). Reference it explicitly:

lizard add postgres
lizard secrets set ANALYTICS_URL='${{postgres-autumn-bear.DATABASE_PRIVATE_URL}}' --service api

Backups and restore

Do not assume scheduled backups or point-in-time recovery. Before a risky migration, export the database yourself and test the restore in a separate database. For example, with pg_dump 18 or newer installed locally:

lizard run --service postgres -- sh -c 'pg_dump "$DATABASE_URL" > backup.sql'

See storage and recovery for a restore plan.

See also

Updated