Fast, focused PostgreSQL-to-PostgreSQL CDC replication.
Documentation · Quickstart · Self-Hosting · API Reference
BunnyDB is a self-hosted PostgreSQL-to-PostgreSQL replication tool built on Change Data Capture (CDC). It handles the hard parts of database replication - schema changes, indexes, foreign keys, and table-level resyncs - so you don't have to.
Self-Hosted: Run on your EC2 instances, local servers, or any Docker host. You own your data, your infrastructure, your uptime.
Cloud Coming Soon: We're running a pilot to validate demand. If this tool is useful to you, a managed cloud version will follow.
- CDC Replication - Real-time streaming via PostgreSQL logical replication
- Schema Sync - On-demand DDL sync (columns, types, defaults, constraints)
- Index Replication - All index types: B-tree, Hash, GIN, GiST, SP-GiST, BRIN
- Foreign Key Handling - Deferred FK strategy for batch consistency
- Table-Level Resync - Resync individual tables without mirror restart
- Zero-Downtime Swap Resync - Shadow table + atomic rename for production safety
- Pause / Resume - Full control over replication lifecycle
- On-Demand Retry - Skip Temporal's backoff circuit for immediate retries
- User Management & RBAC - Admin and viewer roles with JWT auth
- Web UI - Monitor mirrors, manage peers, control replication visually
┌─────────────────────────────────────────────────────────────────┐
│ BunnyDB Stack │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ bunny-ui │ │ bunny-api│ │ temporal │ │ temporal-ui │ │
│ │ :3000 │ │ :8112 │ │ :7233 │ │ :8085 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───────────────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ │
│ ┌───────────────────┴────────────────────┐ │
│ │ bunny-worker │ │
│ │ (Temporal Worker + CDC Engine) │ │
│ └───────────────────┬────────────────────┘ │
│ │ │
│ ┌───────────────────┴────────────────────┐ │
│ │ catalog │ │
│ │ (PostgreSQL :5432) │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
- Docker & Docker Compose
- A PostgreSQL source database with
wal_level = logical
# Clone the latest stable release
git clone --branch v1.0.0 --depth 1 https://github.com/Harshil-Jani/bunnyDB.git
cd bunnyDB
# First-time setup: create .env from template
make setup
# Edit .env with your production values (change passwords!)
# Start BunnyDB
make upThis starts the core services: catalog, temporal, API, worker, and UI.
Tip: Use
make helpto see all available commands.
- UI: http://localhost:3000
- API: http://localhost:8112
- Temporal UI: http://localhost:8085
Default login: admin / admin
make docsAdds a local documentation server at http://localhost:3001.
make devAdds source and destination test databases for development/testing.
make allFor complete self-hosting instructions including production security, reverse proxy setup, and backups, see the Self-Hosting Guide.
# 1. Login
TOKEN=$(curl -s -X POST http://localhost:8112/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}' | jq -r '.token')
# 2. Create source peer
curl -X POST http://localhost:8112/v1/peers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my_source",
"host": "host.docker.internal",
"port": 5432,
"user": "postgres",
"password": "your_password",
"database": "source_db"
}'
# 3. Create destination peer
curl -X POST http://localhost:8112/v1/peers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my_dest",
"host": "host.docker.internal",
"port": 5433,
"user": "postgres",
"password": "your_password",
"database": "dest_db"
}'
# 4. Create mirror
curl -X POST http://localhost:8112/v1/mirrors \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my_mirror",
"source_peer": "my_source",
"destination_peer": "my_dest",
"do_initial_snapshot": true,
"table_mappings": [
{"source_table": "public.users", "destination_table": "public.users"}
]
}'
# 5. Check status
curl http://localhost:8112/v1/mirrors/my_mirror \
-H "Authorization: Bearer $TOKEN" | jq '.status'| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/auth/login |
Authenticate and get JWT token |
| POST | /v1/peers |
Create a peer connection |
| GET | /v1/peers/:name/tables |
List tables on a peer |
| POST | /v1/mirrors |
Create a new mirror |
| GET | /v1/mirrors/:name |
Get mirror status |
| POST | /v1/mirrors/:name/pause |
Pause replication |
| POST | /v1/mirrors/:name/resume |
Resume replication |
| POST | /v1/mirrors/:name/resync |
Full mirror resync |
| POST | /v1/mirrors/:name/resync/:table |
Table-level resync |
| POST | /v1/mirrors/:name/retry |
Immediate retry (skip backoff) |
| POST | /v1/mirrors/:name/sync-schema |
Apply schema changes |
| DELETE | /v1/mirrors/:name |
Drop mirror |
For complete API documentation, see the API Reference.
| Variable | Description | Default |
|---|---|---|
BUNNY_CATALOG_HOST |
Catalog database host | catalog |
BUNNY_CATALOG_PORT |
Catalog database port | 5432 |
BUNNY_CATALOG_USER |
Catalog database user | postgres |
BUNNY_CATALOG_PASSWORD |
Catalog database password | bunnydb |
BUNNY_CATALOG_DATABASE |
Catalog database name | bunnydb |
TEMPORAL_HOST_PORT |
Temporal server address | temporal:7233 |
BUNNY_JWT_SECRET |
JWT signing secret | change-me-in-production |
BUNNY_ADMIN_USER |
Default admin username | admin |
BUNNY_ADMIN_PASSWORD |
Default admin password | admin |
For full configuration details, see Configuration docs.
Your source PostgreSQL must have:
-- postgresql.conf
wal_level = logical
max_replication_slots = 4 -- at least 1 per mirror
max_wal_senders = 4 -- at least 1 per mirrorThe connecting user needs REPLICATION privilege or superuser access.
bunnyDB/
├── flow/ # Go backend (API server + Temporal worker)
├── ui/ # Next.js web UI
├── docs/ # Nextra documentation site
├── landing/ # Static landing page (for GitHub Pages)
├── volumes/ # Docker volume configs
└── docker-compose.yml
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-feature) - Run the dev setup:
docker compose --profile dev up -d - Make changes and test
- Submit a pull request
See Contributing Guide for details.
Elastic License 2.0 (ELv2) - You may use, copy, and modify the software for any purpose except providing it as a managed service to third parties.