Quickstart

Autopg is two Docker images. The first is a drop-in Postgres that configures itself to the machine it boots on. The second, autopg-pool, is a connection pooler that wraps pgbouncer behind a single config file. You can run either on its own. Together they are most of what you need to self-host Postgres in production.

The Postgres image

Anywhere you would run the official postgres image, run autopg instead:

docker run -p 5432:5432 ghcr.io/piercefreeman/autopg:pg18-latest

On startup autopg inspects the host (CPU count, total memory, and disk type), calculates an optimized postgresql.conf, and then hands off to the normal Postgres entrypoint. You get the same Postgres, the same data directory, and the same environment variables (POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB). Image tags follow the major version: pg18, pg17, pg16, pg15, and pg14.

In a compose file:

services:
  postgres:
    image: ghcr.io/piercefreeman/autopg:pg18-latest
    environment:
      POSTGRES_PASSWORD: changeme
    ports:
      - 5432:5432
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Tune it to your workload

The hardware is detected automatically, but you should tell autopg what the database is for. Set AUTOPG_DB_TYPE and the tuning shifts: connection limits, parallel workers, planner costs, and WAL sizing all move with it.

services:
  postgres:
    image: ghcr.io/piercefreeman/autopg:pg18-latest
    environment:
      AUTOPG_DB_TYPE: oltp
      AUTOPG_PRIMARY_DISK_TYPE: SSD
    ports:
      - 5432:5432

Every detected value can be overridden if you know better than the host. See Auto-tuning for the full list and Configuration for the complete environment reference.

Add the pooler

When your app opens more connections than Postgres should hold at once, put autopg-pool in front. It reads a single TOML file: declare your users, the databases they can reach, and the upstream Postgres to route to.

# autopgpool.toml
[[users]]
username = "app"
password = "$APP_PASSWORD"
grants = ["main"]

[pools.main.remote]
host = "postgres"
port = 5432
database = "main"
username = "main_user"
password = "$MAIN_DB_PASSWORD"
services:
  pool:
    image: ghcr.io/piercefreeman/autopg-pool:latest
    ports:
      - 6432:6432
    environment:
      - APP_PASSWORD=changeme
      - MAIN_DB_PASSWORD=changeme
    volumes:
      - ./autopgpool.toml:/etc/autopgpool/autopgpool.toml

Your application now connects to the pooler on port 6432 instead of Postgres directly. See the Load balancer overview for the full picture.

Where to next