2025 · Solo · Open source
postgres-replica
Docker-native logical replication from one PostgreSQL source to many targets, driven by a single YAML file.
Architecture
Mission
Logical replication in PostgreSQL is powerful and fiddly: publications, subscriptions, slots, and a REFRESH every time a table changes. I wanted a container that reads one YAML file and keeps a source in sync with many targets, so I could stop hand-typing the same SQL on every project.
For whom: small teams running Postgres in containers. Constraints: dynamic table add and remove without downtime, cross-schema support, an initial-sync toggle, and a health endpoint an orchestrator can poll.
Manifest
| Layer | Choice | Version | Why |
|---|---|---|---|
| services | Node.js + TypeScript | — | A small reconciler loop over pg; easy to read in one sitting. |
| data | PostgreSQL logical replication | — | Publications and subscriptions do the heavy lifting; the tool only manages them. |
| infra | Docker | — | One image, one YAML mount, one health endpoint. |
| app | YAML config | — | Desired state in a file people already keep in git. |
Decisions
YAML in, replication out. The file is the desired state; the service reconciles publications and subscriptions towards it.
Dynamic table changes without downtime. Adding or removing a table alters the publication and refreshes the subscription instead of rebuilding it.
A health endpoint. Swarm and Kubernetes can tell the difference between "running" and "replicating".
Docker Hub as the distribution channel. No install, one image, environment-driven.
Impact
- Docker Hub pulls
- 1,449
- Commits
- 9
- Targets per source
- many
1,441 image pulls on Docker Hub, 9 commits, and a Medium write-up. It went on to power the Postgres replication tool inside KwikNkap.
What broke
Nothing dramatic in production yet, which is what a nine-commit tool should say. The first thing I would fix: a new table added to the YAML is published immediately but only initial-syncs if the toggle is on, and the health endpoint does not distinguish "subscribed, lagging" from "subscribed, healthy". Lag reporting is the next commit.
Ship log
- First commit
- Write-up published on Medium
- Last release
- Now: 1,449 pulls