{"id":32789407,"url":"https://github.com/thimirasadeesha/postgres-replication-docker","last_synced_at":"2026-04-28T16:01:51.537Z","repository":{"id":321631273,"uuid":"1086591499","full_name":"ThimiraSadeesha/postgres-replication-docker","owner":"ThimiraSadeesha","description":"🐘 PostgreSQL streaming replication with Docker Compose  Complete setup with 1 primary and 2 replicas. Includes hands on tutorials, monitoring guides, and troubleshooting tips for learning database replication.","archived":false,"fork":false,"pushed_at":"2025-10-30T16:40:47.000Z","size":13,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-30T18:28:27.826Z","etag":null,"topics":["docker","docker-compose","postgresql","replica","replication"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThimiraSadeesha.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-30T16:17:44.000Z","updated_at":"2025-10-30T16:41:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"4e39599e-5e15-4bb4-b618-dc375ee52781","html_url":"https://github.com/ThimiraSadeesha/postgres-replication-docker","commit_stats":null,"previous_names":["thimirasadeesha/postgres-replication-docker"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ThimiraSadeesha/postgres-replication-docker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThimiraSadeesha%2Fpostgres-replication-docker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThimiraSadeesha%2Fpostgres-replication-docker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThimiraSadeesha%2Fpostgres-replication-docker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThimiraSadeesha%2Fpostgres-replication-docker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThimiraSadeesha","download_url":"https://codeload.github.com/ThimiraSadeesha/postgres-replication-docker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThimiraSadeesha%2Fpostgres-replication-docker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":282799913,"owners_count":26729199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-05T02:00:05.946Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","postgresql","replica","replication"],"created_at":"2025-11-05T10:01:30.768Z","updated_at":"2025-11-05T10:01:51.773Z","avatar_url":"https://github.com/ThimiraSadeesha.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PostgreSQL Primary-Replica Replication with Docker\n\nA hands-on guide to setting up PostgreSQL streaming replication with one primary and two replica servers using Docker Compose.\n\n![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge\u0026logo=docker\u0026logoColor=white)\n![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16-316192?style=for-the-badge\u0026logo=postgresql\u0026logoColor=white)\n![License](https://img.shields.io/github/license/ThimiraSadeesha/postgres-replication-docker?style=for-the-badge)\n![Stars](https://img.shields.io/github/stars/ThimiraSadeesha/postgres-replication-docker?style=for-the-badge)\n![Forks](https://img.shields.io/github/forks/ThimiraSadeesha/postgres-replication-docker?style=for-the-badge)\n![Issues](https://img.shields.io/github/issues/ThimiraSadeesha/postgres-replication-docker?style=for-the-badge)\n\n## 📋 Table of Contents\n\n- [Overview](#overview)\n- [Architecture](#architecture)\n- [Prerequisites](#prerequisites)\n- [Quick Start](#quick-start)\n- [Configuration](#configuration)\n- [Testing Replication](#testing-replication)\n- [Monitoring](#monitoring)\n- [Troubleshooting](#troubleshooting)\n- [Advanced Usage](#advanced-usage)\n- [Contributing](#contributing)\n\n## 🎯 Overview\n\nThis project demonstrates PostgreSQL streaming replication using Docker containers. It sets up:\n- **1 Primary Server** (read-write)\n- **2 Replica Servers** (read-only)\n\nAll changes made to the primary are automatically replicated to both replicas in real-time using PostgreSQL's built-in streaming replication feature.\n\n## 🏗️ Architecture\n\n```\n┌─────────────────┐\n│   pg-primary    │ (Port 5432)\n│   (Read/Write)  │\n└────────┬────────┘\n         │\n         ├─────────────┬─────────────┐\n         │             │             │\n         ▼             ▼             ▼\n┌────────────────┐ ┌────────────────┐\n│  pg-replica-1  │ │  pg-replica-2  │\n│  (Read-Only)   │ │  (Read-Only)   │\n│  Port 5433     │ │  Port 5434     │\n└────────────────┘ └────────────────┘\n```\n\n## ✅ Prerequisites\n\n- Docker Desktop or Docker Engine (20.10+)\n- Docker Compose V2\n- At least 2GB of available RAM\n- Basic knowledge of PostgreSQL and Docker\n\n## 🚀 Quick Start\n\n1. **Clone the repository**\n   ```bash\n   git clone https://github.com/ThimiraSadeesha/postgres-replication-docker.git\n   cd postgres-replication-docker\n   ```\n\n2. **Make the initialization script executable**\n   ```bash\n   chmod +x init-primary.sh\n   ```\n\n3. **Start the cluster**\n   ```bash\n   docker compose up -d\n   ```\n\n4. **Wait for initialization** (30-60 seconds)\n   ```bash\n   docker compose ps\n   ```\n\n5. **Verify all containers are healthy**\n   ```bash\n   docker compose logs -f\n   ```\n\n## ⚙️ Configuration\n\n### Environment Variables\n\nYou can customize the following variables in `docker-compose.yml`:\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `POSTGRES_USER` | `postgres` | Primary database superuser |\n| `POSTGRES_PASSWORD` | `my_password` | Primary database password |\n| `POSTGRES_DB` | `mydb` | Default database name |\n| Replication User | `replicator` | User for replication |\n| Replication Password | `repl_password` | Password for replication user |\n\n### PostgreSQL Configuration\n\nThe primary server is configured with:\n- `wal_level=replica` - Enables replication\n- `max_wal_senders=10` - Maximum concurrent replication connections\n- `max_replication_slots=10` - Maximum replication slots\n- `hot_standby=on` - Allows read queries on replicas\n\n## 🧪 Testing Replication\n\n### Test 1: Basic Replication\n\n```bash\n  # Create a table on primary\n  docker exec -it postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres -d mydb -c \"CREATE TABLE users (id serial PRIMARY KEY, name text);\"\n\n  # Insert data\n  docker exec -it postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres -d mydb -c \"INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');\"\n\n  # Check primary\n  docker exec -it postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres -d mydb -c \"SELECT * FROM users;\"\n\n  # Check replica-1\n  docker exec -it postgres-replication-docker-pg-replica-1-1 \\\n  psql -U postgres -d mydb -c \"SELECT * FROM users;\"\n\n  # Check replica-2\n  docker exec -it postgres-replication-docker-pg-replica-2-1 \\\n  psql -U postgres -d mydb -c \"SELECT * FROM users;\"\n```\n\n### Test 2: Verify Replication Lag\n\n```bash\n  # On primary - check replication status\n  docker exec -it postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres -c \"SELECT * FROM pg_stat_replication;\"\n```\n\n### Test 3: Read-Only Verification\n\n```bash\n    # Try to write to replica (should fail)\n  docker exec -it postgres-replication-docker-pg-replica-1-1 \\\n  psql -U postgres -d mydb -c \"INSERT INTO users (name) VALUES ('David');\"\n```\n\nExpected output: `ERROR: cannot execute INSERT in a read-only transaction`\n\n## 📊 Monitoring\n\n### Check Replication Status\n\n```bash\n # View replication slots\ndocker exec -it postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres -c \"SELECT slot_name, active, restart_lsn FROM pg_replication_slots;\"\n\n # View replication connections\ndocker exec -it postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres -c \"SELECT client_addr, state, sync_state FROM pg_stat_replication;\"\n```\n\n### View Logs\n\n```bash\n  # All services\ndocker compose logs -f\n\n# Specific service\ndocker compose logs -f pg-primary\ndocker compose logs -f pg-replica-1\ndocker compose logs -f pg-replica-2\n```\n\n## 🔧 Troubleshooting\n\n### Problem: Replicas not starting\n\n**Solution:**\n```bash\n  # Stop and remove all containers and volumes\n  docker compose down -v\n\n# Restart\n  docker compose up -d\n```\n\n### Problem: Replication lag\n\n**Check replication delay:**\n```bash\n  docker exec -it postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres -c \"SELECT pid, usename, application_name, client_addr, state, \n    sent_lsn, write_lsn, flush_lsn, replay_lsn, \n    write_lag, flush_lag, replay_lag \n  FROM pg_stat_replication;\"\n```\n\n### Problem: Connection refused\n\n**Check if primary is ready:**\n```bash\n  docker compose ps\n  docker compose logs pg-primary\n```\n\n## 🎓 Advanced Usage\n\n### Promoting a Replica to Primary\n\nIf the primary fails, you can promote a replica:\n\n```bash\n  # Promote replica-1 to primary\n   docker exec -it postgres-replication-docker-pg-replica-1-1 \\\n  /bin/bash -c \"pg_ctl promote -D /var/lib/postgresql/data\"\n```\n\n### Scaling Replicas\n\nTo add more replicas, edit `docker-compose.yml` and add:\n\n```yaml\npg-replica-3:\n  image: postgres:16\n  depends_on: \n    pg-primary:\n      condition: service_healthy\n  ports:\n    - \"5435:5432\"\n  environment:\n    - POSTGRES_USER=postgres\n    - POSTGRES_PASSWORD=my_password\n  entrypoint: |\n    bash -c \"\n    if [ ! -s /var/lib/postgresql/data/PG_VERSION ]; then\n      echo 'Initializing replica from primary...'\n      until PGPASSWORD=repl_password pg_basebackup -h pg-primary -U replicator -D /var/lib/postgresql/data -R -X stream -c fast -S replication_slot_3\n      do\n        echo 'Waiting for primary...'\n        sleep 2\n      done\n      echo 'Backup complete!'\n    fi\n    docker-entrypoint.sh postgres\n    \"\n  volumes:\n    - pg_replica_3_data:/var/lib/postgresql/data\n```\n\nDon't forget to create the replication slot in `init-primary.sh`:\n```sql\nSELECT * FROM pg_create_physical_replication_slot('replication_slot_3');\n```\n\n### Backup Strategy\n\n```bash\n   # Backup primary database\n  docker exec postgres-replication-docker-pg-primary-1 \\\n  pg_dump -U postgres mydb \u003e backup.sql\n\n  # Restore to primary\n  docker exec -i postgres-replication-docker-pg-primary-1 \\\n  psql -U postgres mydb \u003c backup.sql\n```\n\n## 🛑 Stopping the Cluster\n\n```bash\n   # Stop containers (data persists)\n   docker compose down\n\n  # Stop and remove all data\n   docker compose down -v\n```\n\n## 📚 Learning Resources\n\n- [PostgreSQL Replication Documentation](https://www.postgresql.org/docs/current/high-availability.html)\n- [Docker Compose Documentation](https://docs.docker.com/compose/)\n- [PostgreSQL Streaming Replication](https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION)\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## 📝 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🙏 Acknowledgments\n\n- PostgreSQL Community\n- Docker Community\n- Bitnami for initial inspiration\n\n## 📧 Contact\n\nThimira Sadeesha - [@sadeesha.me](https://www.sadeesha.me/)\n\nProject Link: [https://github.com/ThimiraSadeesha/postgres-replication-docker.git](https://github.com/ThimiraSadeesha/postgres-replication-docker.git)\n\n---\n\n⭐ Star this repository if you find it helpful!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthimirasadeesha%2Fpostgres-replication-docker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthimirasadeesha%2Fpostgres-replication-docker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthimirasadeesha%2Fpostgres-replication-docker/lists"}