Database Read Replicas
TL;DR — A read replica is a second cluster that continuously mirrors your primary database and accepts read-only traffic. Add one from the cluster's Settings page. Use replicas to offload reporting queries, build geographically closer read endpoints, or keep heavy analytics off the primary.
Engine Support
| Engine | Replicas Supported? |
|---|---|
| PostgreSQL | ✅ |
| MySQL | ✅ |
| MongoDB | ✅ |
| Valkey | ✅ |
| Kafka | ❌ (replication is built into the 3-node Cluster tier) |
| OpenSearch | ❌ (sharding/replicas configured at index level) |
Why Use Replicas
- Scale read traffic. Point read-only queries to a replica; reserve the primary for writes.
- Isolate analytics. Reporting queries can use replica resources without slowing the primary.
- Geographic locality. Place a replica in a region close to a remote office or customer base for low-latency reads.
- Protection from runaway queries. A bad analytical query on a replica won't lock tables on the primary.
- Disaster recovery hedge. A replica is a continuously-updated copy of the data — handy alongside (not as a replacement for) backups.
Prerequisites
- The primary cluster must be one of PostgreSQL, MySQL, MongoDB, or Valkey
- An unused subscription plan matching the engine — typically a Starter plan (one plan = one replica)
- The replica defaults to the same region as the primary; we can place it in a different region — open a support ticket to request
Add a Replica
- Open your cluster
- Click Settings in the cluster header
- In the Add a Read Node section:
- Pick an available plan from the dropdown (only unused plans matching the engine appear)
- Click Add Read Node
The replica is provisioned within minutes. It appears under the Replicas tab of the primary cluster with its own status indicator.
View Replicas
The cluster's Replicas tab lists every replica with:
| Column | Description |
|---|---|
| Name | Replica identifier (the primary's name + -replica-<timestamp>) |
| Region | The replica's data center |
| Status | Online / Provisioning / Resizing / Migrating |
| Created | Provisioning date |
Click a replica row to open its own detail page — replicas are full clusters with their own connection details, firewall rules, metrics, pools, and backups.
Connect to a Replica
Each replica has its own Connection tab with a separate URI, host, port, and user. Configure your application to route read-only queries to the replica's URI.
Example — Read / Write Splitting
Most ORMs support multiple database connections:
// Node.js — Prisma + custom router import { PrismaClient } from '@prisma/client' const primary = new PrismaClient({ datasources: { db: { url: process.env.DATABASE_URL } } }) const replica = new PrismaClient({ datasources: { db: { url: process.env.DATABASE_REPLICA_URL } } }) // Use `replica` for SELECTs, `primary` for INSERT/UPDATE/DELETE
# Django — multiple databases with a router DATABASES = { 'default': dj_database_url.parse(os.environ['DATABASE_URL']), 'replica': dj_database_url.parse(os.environ['DATABASE_REPLICA_URL']), } DATABASE_ROUTERS = ['myapp.routers.ReadReplicaRouter']
Some application platforms (Rails, Active Record, Sequelize) have built-in read/write split helpers — consult your framework's docs.
Replication Lag
Replicas are asynchronous — there is always a tiny lag (typically milliseconds, occasionally seconds during heavy write loads or network congestion) between a write on the primary and its appearance on the replica.
Implications:
- ✅ Read-after-read patterns are safe (e.g. listing data)
- ⚠️ Read-after-write patterns can return stale data (e.g. user submits a form, then immediately re-reads from a replica — they may not see their own write yet)
Recommended pattern: route the immediate post-write read back to the primary, but everything else to the replica.
Replicas Have Their Own Configuration
Each replica is a full standalone cluster — its Firewall, Maintenance Window, and Log Forwarding are configured independently. Useful examples:
- Open the replica's firewall only to your analytics team's office
- Forward the replica's slow query log to a Datadog dashboard separate from the primary
- Schedule the replica's maintenance window at a different hour from the primary
Resize and Migrate Replicas
Replicas can be resized or moved to a different region from their Settings page, independently of the primary. Useful when:
- You want the analytics replica on a bigger tier than the primary
- You want to relocate a replica closer to a remote office
Delete a Replica
Open the replica → Settings → Destroy (type the replica name to confirm). The primary keeps running unaffected.
💡 Subscription: destroying the replica does not cancel its plan. Cancel the plan from
/cloudpanel/account/plansif you don't need it any more.
Best Practices
- Don't write to a replica. Replicas are read-only; writes are rejected by the engine.
- Use the replica's URI explicitly. Don't rely on DNS or load balancers to do read/write splitting — drivers handle it more reliably.
- Monitor replication lag. Use engine-specific queries (
pg_stat_replication,SHOW SLAVE STATUS, MongoDBrs.status(), ValkeyINFO replication) to alert on lag spikes. - Match replica tier to workload. A Starter replica is great for moderate analytics. For heavy BI workloads, use an HA replica.
- Resize replicas during off-peak. Resize lags replication; do it when traffic is low.
Troubleshooting
Replica creation fails with "no plans available"
Buy another database plan from /cloudpanel/account/plans matching the primary's engine.
Replica is stuck on "Provisioning"
First-time provisioning typically takes 5–10 minutes (the replica must copy the primary's data). Check back after 15 minutes; if it's still stuck, open a support ticket.
Replica returns stale data
That's replication lag. Expected. If consistent reads matter, route the affected query to the primary.
"Cannot execute INSERT" on the replica
Replicas are read-only. Send writes to the primary's URI.
Replica lag grows over time
A long-running transaction on the replica can prevent garbage collection — kill or restart the analytics process. If the primary is write-saturated, consider an HA upgrade.