Docker

PgCache is distributed as a Docker image. The container bundles an embedded PostgreSQL instance for the cache database, so there is nothing else to run. For the fastest path to a working proxy, see Getting Started; this page covers production deployment.

Image and Ports

docker run -d -p 5432:5432 -p 9090:9090 pgcache/pgcache \
  --upstream postgres://user:password@your-db-host:5432/myapp
PortPurpose
5432PostgreSQL wire protocol — point your application here
9090HTTP endpoint for Prometheus metrics and health checks

Security: the metrics/health port is unauthenticated. Publish it only to trusted/internal networks, not the public internet. See Monitoring.

Checking the Origin

Before the first run, ask the image whether the origin is ready. It connects with the same settings the proxy would use and reports each requirement with a fix:

docker run --rm pgcache/pgcache check \
  --upstream postgres://user:password@your-db-host:5432/myapp
pgcache check: origin user@your-db-host:5432/myapp

  PASS  connection             PostgreSQL 18.1
  PASS  server version         PostgreSQL 18.1
  FAIL  wal_level              wal_level is 'replica'; logical replication needs 'logical'
        fix: ALTER SYSTEM SET wal_level = logical;
             then restart PostgreSQL (a reload is not enough).
  PASS  replication slots      0 of 10 replication slots and 0 of 10 wal senders in use
  PASS  role privileges        user has REPLICATION and CREATE on the database
  ...
  WARN  primary keys           2 of 17 tables have no primary key and are forwarded, never cached: ...

9 passed, 1 warnings, 1 failed
Origin is not ready for pgcache. Fix the failures above and run the check again.

A failure exits with status 1 and means the proxy would not start or would not be safe to run; a warning means it starts but the named tables are forwarded rather than cached. Remediations are worded for the detected host: self-managed PostgreSQL, Amazon RDS and Aurora, Cloud SQL, or Neon. The checks are: connection, server version, wal_level, replication slot and WAL sender capacity, role privileges, existing publication and slot, a logical replication connection, table ownership, primary keys, views, row-level security, and pg_stat_statements. ALLOWED_TABLES scopes the table checks to the tables you intend to cache.

No embedded PostgreSQL is initialised in check mode, so the command is quick and leaves nothing behind. The same report is available from the binary as pgcache --check.

Docker Compose

services:
  pgcache:
    image: pgcache/pgcache
    restart: always
    ports:
      - "5432:5432"
      - "9090:9090"
    environment:
      UPSTREAM_URL: postgres://user:password@db:5432/myapp
      NUM_WORKERS: 4
      PUBLICATION: pgcache_pub
      SLOT: pgcache_slot
    healthcheck:
      test: ["CMD", "wget", "-qO", "/dev/null", "http://127.0.0.1:9090/healthz"]
      interval: 10s
      timeout: 3s
      retries: 3

Environment variables map to PgCache’s CLI options — see the Configuration reference for the full list.

Mounting a TOML config

For version-controlled configuration, mount a TOML file and point CONFIG_FILE at it:

services:
  pgcache:
    image: pgcache/pgcache
    restart: always
    ports:
      - "5432:5432"
      - "9090:9090"
    volumes:
      - ./pgcache.toml:/etc/pgcache/config.toml:ro
    environment:
      CONFIG_FILE: /etc/pgcache/config.toml

CLI arguments and environment variables override values from the mounted file, so you can keep a base config in TOML and override per-environment values through the environment.

Mounting TLS certificates

To terminate TLS for client connections, mount the certificate and key and reference them in config (tls_cert / tls_key), or pass them as base64-encoded environment variables (PGCACHE_TLS_CERT / PGCACHE_TLS_KEY). See TLS Support.

    volumes:
      - ./certs/server.crt:/etc/pgcache/server.crt:ro
      - ./certs/server.key:/etc/pgcache/server.key:ro

Health Checks

The HTTP port exposes two probes for orchestrators and load balancers:

  • GET /healthz — liveness; returns 200 whenever the process is running.
  • GET /readyz — readiness; returns 200 when the cache is running, 503 otherwise.

The image declares its own HEALTHCHECK against /healthz (10 s interval, 3 s timeout, 3 retries); the compose healthcheck block above overrides it and is only needed to change those values. The image ships BusyBox wget, not curl. Use /healthz for the container healthcheck and /readyz to gate traffic in a load balancer or Kubernetes deployment. See Monitoring → Health Checks.

Restart Policy

Use restart: always (or unless-stopped) so the container recovers from crashes. Note the interaction with the replication slot: PgCache drops its slot on a graceful stop, but a crash leaves the slot behind on the origin, where it retains WAL until the container restarts and resumes consuming it. An automatic restart policy keeps that window short. Understand this behavior — and how to detect a stuck slot — before running in production: see Operations → The Replication Slot.

Resource Sizing

  • CPU / workers: set NUM_WORKERS to match the connection concurrency you expect; it defaults to a small value suitable for getting started.
  • Memory & disk: the cache holds hot data in the embedded PostgreSQL instance. PgCache bounds itself automatically — by a memory budget (80% of detected RAM by default, lower it with MEMORY_LIMIT) and by cache-volume disk pressure (auto-derived from free space, or cap it with DISK_LIMIT). Give the container enough RAM and disk for your working set. See Configuration → Cache Behavior.
  • Cold start: the cache is reset on every container start and warms from scratch. For planned cutovers, pre-populate hot queries with pinned_queries — see Operations → Cache Warm-Up.