Design promise: a plain
make upstarts only the PostgreSQL server. Every feature below is gated behind a Docker Compose profile, so it consumes no CPU/RAM until you explicitly enable it. All features are present in the repo — anyone who needs one just turns it on.
| Feature | Profile | Command | Default | Idle cost when ON | Off by default? |
|---|---|---|---|---|---|
| Core PostgreSQL 17 | — | make up |
always | (the DB itself) | n/a |
| Manual backup/restore | — | make backup / make restore |
always available | none (runs on demand) | n/a |
| Scheduled backups | backup |
make up-backup |
OFF | ~ idle, ≤128 MB cap | ✅ |
| Connection pooler (PgBouncer) | pooler |
make up-pooler |
OFF | ~5–15 MB, ≤96 MB cap | ✅ |
| Web admin UI (Adminer) | ui |
make up-ui |
OFF | ~10–20 MB, ≤128 MB cap | ✅ |
| Metrics exporter | metrics |
make up-metrics |
OFF | ~10–20 MB, ≤96 MB cap | ✅ |
| Import from source | — | script | always available | none (runs on demand) | n/a |
| Everything at once | all | make up-all |
OFF | sum of the above | ✅ |
Each optional service has a hard
mem_limit+cpuscap, so even when ON it cannot slow your laptop. Turn any of them off again withmake down(stops the whole stack) and bring back just core withmake up.
Why: Postgres max_connections is only 50 and shared. A pooler lets many app
connections (e.g. NestJS in watch mode) share a few real ones.
make up-pooler
# App connects to port 6432 instead of 15409:
# postgresql://local_dev:<password>@127.0.0.1:6432/local_dbTune in .env: PGBOUNCER_POOL_MODE (transaction|session), MAX_CLIENT_CONN,
DEFAULT_POOL_SIZE.
Why: automated, rotated pg_dumps without you remembering to run them.
make up-backup # backs up on BACKUP_SCHEDULE into ./backupsTune in .env: BACKUP_SCHEDULE (@daily, @hourly, or cron), and retention
BACKUP_KEEP_DAYS/WEEKS/MONTHS. Manual backup/restore still works anytime via
make backup / make restore — see doc 7.
Why: a browser GUI for the DB without installing anything on the host. Adminer is a single lightweight container (far lighter than pgAdmin).
make up-ui # open http://localhost:8080
# System: PostgreSQL · Server: postgres · User/DB: from your .envWhy: expose Postgres metrics for Prometheus/Grafana when you want observability.
make up-metrics # metrics at http://localhost:9187/metricsPoint a Prometheus scrape at localhost:9187. (Prometheus/Grafana themselves are
intentionally not bundled — add them in your own monitoring stack if needed.)
A fully optional, on-demand workflow (no running service). See doc 11 — Import from Source.
Extensions like PostGIS or TimescaleDB are deliberately not baked in
(they enlarge the image and can be heavy). If you need them, add the package to
the Dockerfile (e.g. postgresql-17-postgis-3, timescaledb-2-postgresql-17),
add to shared_preload_libraries if required, rebuild, and CREATE EXTENSION.
This keeps the default image fast for everyone who doesn't need them.
docker compose --profile pooler --profile ui up -d # just these two
make up-all # all optional services
make down # stop everything
make up # back to core only✅ Back to the README »