TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-redis-postgres-pgpool-docker/llms.txt
Use this file to discover all available pages before exploring further.
docker/pgpool/docker-compose.yaml starts a complete PostgreSQL 16 streaming-replication cluster — one primary node and two asynchronous replicas — all behind a Pgpool-II load balancer. The entire topology runs inside the single tripolskypetr/pgpool:latest container, making it practical to run a production-representative database setup on a development laptop without any external orchestration. The application connects to :5432 as if it were a plain Postgres endpoint; Pgpool transparently routes writes to the primary and distributes reads across the replicas.
Why Run a Cluster in Development?
On a single-node PostgreSQL instance, a write immediately followed by aSELECT appears perfectly atomic. Both operations reach the same OS process, the same shared-memory buffer pool, and the same WAL writer. Code that relies on this behaviour passes every test you throw at it.
On a replica cluster, writes go to the primary but reads can be served by a replica that has not yet received the corresponding WAL segment. The window can be milliseconds, but it is real. Code that blindly reads back what it just wrote — without using the same connection or a synchronous_commit guarantee — can silently see stale data. In production, this manifests as duplicate rows, missed updates, or corrupted trading state that is nearly impossible to reproduce locally.
Running the Pgpool cluster in development surfaces these bugs early, before they reach production. If your service logic works correctly against the cluster, it will be safe on any streaming-replication setup.
Architecture
| Layer | Role |
|---|---|
| Pgpool-II :5432 | Single connection endpoint for the application. Parses queries and routes them — writes to the primary, reads to replicas. |
| postgres-primary | Accepts all write transactions. Streams WAL to both replicas in real time. |
| replica-1 / replica-2 | Hot standbys. Accept read-only queries. Receive WAL from the primary asynchronously. |
Starting the Cluster
Launch the container
pg_basebackup to clone each replica. This takes approximately 60–90 seconds.Monitor startup progress
:5432.Checking Readiness
The healthcheck command embedded in the compose file probes the Pgpool endpoint directly:Persistent Data
Cluster data (primary WAL, replica data directories, Pgpool state) is bind-mounted from inside the container todocker/pgpool/data/ on your host. This directory is gitignored, so it will not accidentally end up in version control.
Because the data persists on disk, subsequent docker-compose up invocations start in seconds — the replica clone only runs on first boot when docker/pgpool/data/ is empty.
To reset the cluster to a clean state:
Single-Node Alternative
For CI pipelines or experiments that do not involve replication-lag safety,docker/postgres/docker-compose.yaml runs a plain postgres:16-alpine node on the same port:
Connection String
The application always connects through the single Pgpool-II endpoint at When the app runs inside Docker, replace
:5432. It does not need to know which node is currently primary, and it does not need to manage separate read/write connection pools. Pgpool handles query routing transparently.localhost with host.docker.internal (see the .env.example file).