Modern PostgreSQL Control Plane for Enterprise Cluster Management
pgControlPlane is a comprehensive, production-ready control plane for managing PostgreSQL clusters with high availability, automated failover, backup orchestration, and advanced observability. It seamlessly integrates all pgElephant components (pgbalancer, pgBackRest, pgraft, FauxDB, pgSentinel) into a unified cluster management platform.
- Multi-Cluster Management: Manage multiple PostgreSQL clusters from a single control plane
- Automated Failover: Intelligent failover with configurable policies and safety checks
- Blue-Green Deployments: Zero-downtime upgrades and migrations
- Backup Orchestration: Automated backup scheduling with pgBackRest and WAL-G integration
- Configuration Management: Centralized configuration with drift detection and auto-remediation
- Connection Pooling: Integrated pgbalancer management with automatic configuration updates
- Dual API: gRPC for performance + REST for convenience with OpenAPI specs
- PostgreSQL Persistence: Production-ready state storage with migrations
- OpenTelemetry: Complete observability with traces, metrics, and logs
- WebSocket Streaming: Real-time cluster status and event notifications
- Kubernetes Native: CRDs, operator, and Helm charts for K8s deployments
- Multi-Cloud: Works on VMs, bare metal, and Kubernetes across all cloud providers
- Smart Reconciliation: Continuous state reconciliation with configurable intervals
- Health Scoring: Advanced health metrics for intelligent decision-making
- Quorum-Based Operations: Safe promotions with quorum requirements
- Automated Healing: Self-healing clusters with automatic node recovery
- Point-in-Time Recovery: PITR support with backup/restore orchestration
- Monitoring Integration: Built-in Prometheus, Grafana, and pgSentinel integration
- mTLS: Mutual TLS between control plane and agents
- RBAC: Role-based access control with fine-grained permissions
- Vault Integration: Secret management with HashiCorp Vault
- Audit Logging: Complete audit trail for compliance
- JWT Authentication: Modern token-based authentication with refresh tokens
⚡ Deploy a complete cluster in one command:
cd pgControlPlane
./scripts/deploy-full-cluster.sh --name mycluster --nodes 3This single command deploys:
- ✅ 3-node PostgreSQL cluster with automated failover
- ✅ pgbalancer for connection pooling and load balancing
- ✅ pgBackRest for automated backups
- ✅ pgSentinel for real-time monitoring
- ✅ FauxDB for MongoDB compatibility layer
- ✅ Control plane agents on all nodes
See QUICKSTART.md for detailed instructions.
- Go 1.22+
- PostgreSQL 14+ (optional, managed by control plane)
- Docker & Docker Compose (for local deployment)
- Kubernetes 1.27+ (optional, for production K8s deployment)
# Download latest release
curl -L https://github.com/pgElephant/pgControlPlane/releases/latest/download/pgcp-linux-amd64.tar.gz | tar xz
sudo mv pgcp /usr/local/bin/
# Verify installation
pgcp versiongit clone https://github.com/pgElephant/pgControlPlane
cd pgControlPlane
make build
sudo make install# Deploy the complete pgElephant stackcd pgControlPlane
docker-compose -f deployments/complete-stack.yaml up -d
# Verify all services are running
docker-compose -f deployments/complete-stack.yaml ps
# Access the cluster
psql postgresql://postgres:postgres@localhost:5435/productionServices included:
- pgControlPlane API: http://localhost:8080
- pgbalancer: localhost:5435
- pgSentinel Dashboard: http://localhost:3000
- Grafana: http://localhost:3001 (admin/admin)
- Prometheus: http://localhost:9091
- 3 PostgreSQL nodes with streaming replication
# Add Helm repository
helm repo add pgelephant https://pgelephant.github.io/charts
helm repo update
# Install with Helm
helm install pgcontrolplane pgelephant/pgcontrolplane \
--namespace pgcontrolplane \
--create-namespace \
--set database.url="postgres://user:pass@host:5432/pgcp"# Set up database
createdb pgcontrolplane
make migrate
# Configureexport PGCP_DATABASE_URL="postgres://localhost:5432/pgcontrolplane"export PGCP_LOG_LEVEL="info"# Run control plane
make run
# Or run with Docker Compose
docker-compose up -dOption 1: Automated Deployment (Recommended)
# Deploy complete cluster with all components
./scripts/deploy-full-cluster.sh \
--name production \
--nodes 3 \
--version 16.1 \
--replication async
# Output includes connection info and all service URLsOption 2: API-based Deployment
# Provision via orchestrator API
curl -X POST http://localhost:8080/api/v1/orchestrator/provision \
-H "Content-Type: application/json" \
-d '{ "name": "production", "postgres_version": "16.1", "node_count": 3, "region": "us-east-1", "enable_pgbalancer": true, "enable_pgbackrest": true, "enable_pgraft": false, "enable_fauxdb": true, "enable_pgsentinel": true, "replication_mode": "async", "backup_schedule": "0 2 * * *", "instance_type": "m5.large", "storage_gb": 100, "extensions": ["pg_stat_statements", "pg_stat_insights"] }'# Check cluster status
curl http://localhost:8080/api/v1/clusters/production/statusOption 3: Kubernetes CRD
apiVersion: controlplane.pgelephant.com/v1kind: PgClustermetadata:
name: productionspec:
name: productionpostgresVersion: "16.1"nodeCount: 3enablePgBalancer: trueenablePgBackRest: trueenablePgSentinel: truepgControlPlane seamlessly orchestrates all pgElephant components:
- Purpose: Intelligent connection pooling and load distribution
- Features: Round-robin/least-connected balancing, REST API control, MQTT clustering
- Integration: Auto-configured with backend nodes, health checks, automatic failover
- Access: Clients connect through pgbalancer for optimal performance
- Purpose: Automated backup and point-in-time recovery
- Features: Full/incremental/differential backups, encryption, compression
- Integration: Scheduled backups, retention policies, restore automation
- Storage: S3, Azure Blob, GCS, or local filesystem
- Purpose: Strong consistency with distributed consensus
- Features: Leader election, log replication, etcd-compatible API
- Integration: Alternative to streaming replication for CP guarantees
- Use Case: Financial systems, inventory management, critical data
- Purpose: Comprehensive cluster monitoring and alerting
- Features: Query analytics, replication monitoring, performance insights
- Integration: Auto-discovers all nodes, tracks metrics, generates alerts
- Dashboard: Beautiful web UI with real-time updates
- Purpose: MongoDB API compatibility for PostgreSQL
- Features: MongoDB wire protocol, JSON document storage, MongoDB query language
- Integration: Transparently translates MongoDB requests to PostgreSQL
- Use Case: Migrate MongoDB applications to PostgreSQL without code changes
- Purpose: Deep query performance analysis
- Features: Query tracking, execution plans, performance trends
- Integration: Installed on all nodes, data aggregated by pgSentinel
- Benefits: Identify slow queries, optimize performance
┌─────────────┐
│ Clients │
└──────┬──────┘
│
┌──────▼─────────┐ ┌──────────────┐
│ pgbalancer │◄─────┤ pgControlPlane│
│ (Port 5433) │ │ (Port 8080) │
└───┬───┬───┬────┘ └───────┬───────┘
│ │ │ │
┌───▼───▼───▼────┐ ┌─────────▼─────────┐
│ PostgreSQL │◄───┤ Agents │
│ Nodes (1-N) │ │ (on each node) │
│ + pg_stat_ │ └───────────────────┘
│ insights │
└────────────────┘ │
│ │
┌───────▼──────────┐ ┌────────▼─────────┐
│ pgBackRest │ │ pgSentinel │
│ (Backups) │ │ (Monitoring) │
└──────────────────┘ └──────────────────┘
│
┌───────▼────────┐
│ FauxDB │
│ (Testing) │
└────────────────┘
┌─────────────────┐
│ Clients │
│ Applications │
└────────┬────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌─────────▼────────┐ │ ┌────────▼─────────┐
│ pgbalancer │ │ │ pgControlPlane │
│ Connection Pool │ │ │ Control API │
│ Load Balancer │ │ │ (Port 8080) │
│ (Port 5433) │◄────┼─────┤ │
└─────────┬────────┘ │ └────────┬─────────┘
│ │ │
┌────────────┼──────────────┘ │
│ │ │
│ ┌─────────▼───────────────────────┐ │
│ │ PostgreSQL Cluster Nodes │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Node 1 (Primary) │◄───┼────┤
│ │ │ + Agent │ │ │
│ │ │ + pg_stat_insights │ │ │
│ │ └───────────┬─────────────┘ │ │
│ │ │ Replication │ │
│ │ ┌───────────▼─────────────┐ │ │
│ │ │ Node 2 (Replica) │◄───┼────┤
│ │ │ + Agent │ │ │
│ │ │ + pg_stat_insights │ │ │
│ │ └───────────┬─────────────┘ │ │
│ │ │ Replication │ │
│ │ ┌───────────▼─────────────┐ │ │
│ │ │ Node 3 (Replica) │◄───┼────┤
│ │ │ + Agent │ │ │
│ │ │ + pg_stat_insights │ │ │
│ │ └─────────────────────────┘ │ │
│ └────────┬────────────────────────┘ │
│ │ │
│ ┌────────▼──────────┐ ┌───────────▼──────────┐
│ │ pgBackRest │ │ pgSentinel │
│ │ Backup System │ │ Monitoring Hub │
│ │ - Full/Incr │ │ - Dashboard │
│ │ - PITR │ │ - Alerts │
│ │ - S3 Storage │ │ - Analytics │
│ └───────────────────┘ └──────────┬───────────┘
│ │
│ ┌──────────▼──────────┐
│ │ FauxDB │
│ │ MongoDB Compat │
└────────────────────────────┤ - Wire Protocol │
│ - JSON Documents │
│ - Query Trans. │
└─────────────────────┘
Legend:
━━━ Data Flow ◄─── Management/Control
│ Replication ┌─┐ Component/Service
┌───────────────────────── pgControlPlane ──────────────────────────┐
│ │
│ ┌───────────────────── API Layer ───────────────────────┐ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ REST │ │ gRPC │ │ WebSocket │ │ │
│ │ │ (8080) │ │ (9090) │ │ (8081) │ │ │
│ │ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │ │
│ └───────┼───────────────┼─────────────────┼───────────┘ │
│ │ │ │ │
│ ┌───────▼───────────────▼─────────────────▼───────────┐ │
│ │ Service Layer │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ │
│ │ │ Cluster │ │ Reconciler │ │ Agent │ │ │
│ │ │ Manager │ │ Loop │ │Coordinator│ │ │
│ │ └──────────────┘ └──────────────┘ └───────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ │
│ │ │ Backup │ │ Orchestrator │ │ WebSocket │ │ │
│ │ │ Manager │ │ (Deploy) │ │ Manager │ │ │
│ │ └──────────────┘ └──────────────┘ └───────────┘ │ │
│ └────────────────────────┬──────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼─────────────────────────────────┐ │
│ │ PostgreSQL State Store (Control Plane DB) │ │
│ │ │ │
│ │ Tables: clusters | nodes | agents | backups │ │
│ │ events | configurations │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────── Observability Stack ─────────────────┐ │
│ │ │ │
│ │ • OpenTelemetry • Prometheus • Metrics (Port 2112) │ │
│ │ • Traces • Logs • Grafana Dashboards │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────┘
- API Layer: Accepts requests via REST, gRPC, or WebSocket
- Service Layer: Business logic for cluster operations
- Persistence Layer: PostgreSQL for state + event sourcing
- Agent Communication: mTLS-secured commands to agents
- Observability: OpenTelemetry spans and metrics throughout
- CRUD operations for clusters and nodes
- Health check orchestration
- Topology management
- Continuous reconciliation loop (default: 30s)
- Detects and repairs drift
- Automated failover when needed
- Configuration synchronization
- Agent registration and heartbeat
- Command dispatch with retry logic
- Health monitoring and pruning
- Scheduled backup orchestration
- PITR support
- Backup verification
- Retention policy enforcement
# Server
PGCP_HTTP_PORT=8080
PGCP_GRPC_PORT=9090
PGCP_WS_PORT=8081
# Database
PGCP_DATABASE_URL=postgres://localhost:5432/pgcontrolplane
PGCP_DATABASE_MAX_CONNS=100
PGCP_DATABASE_MAX_IDLE_CONNS=10
# Security
PGCP_JWT_SECRET=your-secret-key
PGCP_JWT_EXPIRY=24h
PGCP_TLS_CERT=/path/to/cert.pem
PGCP_TLS_KEY=/path/to/key.pem
PGCP_MTLS_CA=/path/to/ca.pem
# Reconciliation
PGCP_RECONCILE_INTERVAL=30s
PGCP_PROMOTION_TIMEOUT=30s
PGCP_SAFE_PROMOTE=true
# Agent
PGCP_AGENT_TTL=5m
PGCP_AGENT_PRUNE_INTERVAL=1m
# Observability
PGCP_LOG_LEVEL=info
PGCP_LOG_FORMAT=json
PGCP_METRICS_PORT=2112
PGCP_TRACING_ENDPOINT=http://jaeger:14268/api/traces
# Features
PGCP_AUTO_FAILOVER=true
PGCP_AUTO_HEALING=true
PGCP_CONFIG_DRIFT_DETECTION=true# config.yamlserver:
http_port: 8080grpc_port: 9090ws_port: 8081read_timeout: 30swrite_timeout: 30sdatabase:
url: postgres://localhost:5432/pgcontrolplanemax_connections: 100max_idle_connections: 10connection_timeout: 10ssecurity:
jwt:
secret: ${JWT_SECRET}expiry: 24htls:
enabled: truecert_file: /etc/pgcp/tls/cert.pemkey_file: /etc/pgcp/tls/key.pemca_file: /etc/pgcp/tls/ca.pemrbac:
enabled: truereconciler:
interval: 30spromotion_timeout: 30ssafe_promote: truemax_concurrent_reconciles: 5agents:
ttl: 5mprune_interval: 1mcommand_timeout: 2mobservability:
logging:
level: infoformat: jsonmetrics:
enabled: trueport: 2112tracing:
enabled: trueendpoint: http://jaeger:14268/api/tracessample_rate: 0.1features:
auto_failover: trueauto_healing: trueconfig_drift_detection: truebackup_orchestration: trueFull OpenAPI/Swagger documentation available at /api/docs
# Login
POST /api/v1/auth/login
{
"username": "admin",
"password": "secret"
}
# Response
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"expires_in": 86400
}# List clusters
GET /api/v1/clusters
# Get cluster
GET /api/v1/clusters/{id}
# Create cluster
POST /api/v1/clusters
{
"name": "production",
"region": "us-east-1",
"postgres_version": "16.1",
"replication_mode": "sync",
"auto_failover": true
}
# Update cluster
PUT /api/v1/clusters/{id}
# Delete cluster
DELETE /api/v1/clusters/{id}
# Get cluster status
GET /api/v1/clusters/{id}/status
# Get cluster topology
GET /api/v1/clusters/{id}/topology
# Get cluster metrics
GET /api/v1/clusters/{id}/metrics# List nodes
GET /api/v1/clusters/{cluster_id}/nodes
# Add node
POST /api/v1/clusters/{cluster_id}/nodes
{
"host": "192.168.1.10",
"port": 5432,
"role": "replica",
"priority": 100
}
# Remove node
DELETE /api/v1/clusters/{cluster_id}/nodes/{node_id}
# Promote node
POST /api/v1/clusters/{cluster_id}/nodes/{node_id}/promote
{
"force": false
}# List backups
GET /api/v1/clusters/{cluster_id}/backups
# Create backup
POST /api/v1/clusters/{cluster_id}/backups
{
"type": "full",
"compression": true
}
# Restore backup
POST /api/v1/clusters/{cluster_id}/restore
{
"backup_id": "backup-123",
"point_in_time": "2024-01-15T10:30:00Z"
}See api/proto/controlplane.proto for full service definitions
serviceControlPlane {
rpcCreateCluster(CreateClusterRequest) returns (Cluster);
rpcGetCluster(GetClusterRequest) returns (Cluster);
rpcListClusters(ListClustersRequest) returns (ListClustersResponse);
rpcUpdateCluster(UpdateClusterRequest) returns (Cluster);
rpcDeleteCluster(DeleteClusterRequest) returns (Empty);
rpcAddNode(AddNodeRequest) returns (Node);
rpcRemoveNode(RemoveNodeRequest) returns (Empty);
rpcPromoteNode(PromoteNodeRequest) returns (PromoteNodeResponse);
rpcStreamClusterEvents(StreamClusterEventsRequest) returns (streamClusterEvent);
}// Connectconstws=newWebSocket('ws://localhost:8081/api/v1/ws');// Subscribe to cluster eventsws.send(JSON.stringify({action: 'subscribe',cluster_id: 'production'}));// Receive eventsws.onmessage=(event)=>{constdata=JSON.parse(event.data);console.log('Event:',data);};Prometheus metrics exposed on port 2112:
# Control Plane Metrics
pgcp_clusters_total
pgcp_nodes_total
pgcp_reconcile_runs_total
pgcp_reconcile_duration_seconds
pgcp_promotions_total
pgcp_promotions_failed_total
pgcp_failovers_total
pgcp_agent_commands_total
pgcp_agent_commands_duration_seconds
pgcp_backup_operations_total
pgcp_backup_size_bytes
# Per-Cluster Metrics
pgcp_cluster_health_score
pgcp_cluster_replication_lag_seconds
pgcp_cluster_nodes_up
pgcp_cluster_nodes_down
Structured JSON logs with correlation IDs:
{
"level": "info",
"timestamp": "2024-01-15T10:30:45Z",
"correlation_id": "req-123-abc",
"component": "reconciler",
"cluster_id": "production",
"message": "promoting node to primary",
"node_id": "node-2",
"reason": "primary_down"
}OpenTelemetry traces for all operations:
Promote Node
├── Check Quorum (15ms)
├── Validate Candidate (8ms)
├── Send Promote Command (120ms)
│ ├── Agent Call (100ms)
│ └── Retry Logic (20ms)
├── Update State (25ms)
└── Notify Watchers (10ms)
Total: 178ms
version: '3.8'services:
pgcontrolplane:
image: pgelephant/pgcontrolplane:latestports:
- "8080:8080"
- "9090:9090"
- "2112:2112"environment:
PGCP_DATABASE_URL: postgres://pgcp:secret@postgres:5432/pgcontrolplanePGCP_LOG_LEVEL: infodepends_on:
- postgrespostgres:
image: postgres:16environment:
POSTGRES_DB: pgcontrolplanePOSTGRES_USER: pgcpPOSTGRES_PASSWORD: secretvolumes:
- pgcp-data:/var/lib/postgresql/datavolumes:
pgcp-data:apiVersion: v1kind: Namespacemetadata:
name: pgcontrolplane
---
apiVersion: apps/v1kind: Deploymentmetadata:
name: pgcontrolplanenamespace: pgcontrolplanespec:
replicas: 3selector:
matchLabels:
app: pgcontrolplanetemplate:
metadata:
labels:
app: pgcontrolplanespec:
containers:
- name: pgcontrolplaneimage: pgelephant/pgcontrolplane:latestports:
- containerPort: 8080name: http
- containerPort: 9090name: grpc
- containerPort: 2112name: metricsenv:
- name: PGCP_DATABASE_URLvalueFrom:
secretKeyRef:
name: pgcp-secretskey: database-urllivenessProbe:
httpGet:
path: /healthzport: 8080initialDelaySeconds: 30periodSeconds: 10readinessProbe:
httpGet:
path: /readyzport: 8080initialDelaySeconds: 5periodSeconds: 5# Minimal single-node cluster for developmentexport ENABLE_PGSENTINEL=false
export ENABLE_FAUXDB=false
export INSTANCE_TYPE=t3.small
./scripts/deploy-full-cluster.sh --name dev --nodes 1# 5-node cluster with synchronous replication
./scripts/deploy-full-cluster.sh \
--name production \
--nodes 5 \
--version 16.1 \
--replication sync \
--region us-east-1# Strong consistency with pgraft
./scripts/deploy-full-cluster.sh \
--name financial \
--nodes 5 \
--with-raft# Primary region
./scripts/deploy-full-cluster.sh \
--name primary \
--nodes 3 \
--region us-east-1
# Standby region
./scripts/deploy-full-cluster.sh \
--name standby \
--nodes 3 \
--region us-west-2# Full stack with all testing toolsexport ENABLE_FAUXDB=true
export ENABLE_PGSENTINEL=true
./scripts/deploy-full-cluster.sh \
--name testing \
--nodes 3
# Run automated tests
curl -X POST http://localhost:5000/api/tests/runSee the examples/ directory for more:
basic-cluster/- Simple 3-node cluster setupha-cluster/- High-availability configurationkubernetes/- Complete Kubernetes deployment- Full documentation at QUICKSTART.md
# Run unit tests
make test# Run integration tests
make test-integration
# Run end-to-end tests
make test-e2e
# Run with coverage
make test-coverage
# Run benchmarks
make benchWe welcome contributions! Please see CONTRIBUTING.md for details.
Apache License 2.0 - see LICENSE file for details.
- Website: https://www.pgelephant.com/pgcontrolplane
- Documentation: https://docs.pgelephant.com/pgcontrolplane
- GitHub: https://github.com/pgElephant/pgControlPlane
- Discord: https://discord.gg/pgelephant
- Blog: https://www.pgelephant.com/blog
Built with ❤️ by the pgElephant team and contributors.
Special thanks to the PostgreSQL community and the following projects:
- PostgreSQL
- pgBackRest
- Patroni
- etcd
- OpenTelemetry