Definition
- Multi-AZ – provisions a synchronous standby replica in a different Availability Zone; every committed write is replicated before acknowledgment, and RDS fails over automatically on primary failure.
- Read replica – an asynchronous copy that accepts read-only queries to offload reads from the primary; replication lag means data may be slightly behind.
- Failover behavior – Multi-AZ failover is automatic on the same endpoint in one to two minutes; a read replica must be manually promoted, which breaks its replication link.
- Use together – production databases use both: Multi-AZ for availability, read replicas for read scaling.
Think of the main ledger at National Bank of India. Multi-AZ is like having a second clerk in another branch who writes down every single transaction at the exact same moment as the main clerk, so if the main clerk suddenly leaves, the second clerk instantly becomes the main clerk with an identical, up-to-the-second ledger -- but customers never go to that second clerk for answers. A read replica is different: it is like photocopying the ledger every few seconds and placing the copies in several reading rooms, so many people who only want to read can do so without crowding the main clerk, accepting that a copy might be a few seconds behind.
Understanding the Concepts
What is RDS Multi-AZ?
Multi-AZ is about staying up. When you enable it, RDS creates a standby in another Availability Zone and replicates synchronously, meaning a write is not acknowledged to the application until both the primary and the standby have persisted it. This keeps the standby perfectly current. The standby is not readable -- you cannot send queries to it -- it exists purely to take over.
// With Multi-AZ, the app uses ONE endpoint for reads and writes
package com.bank.persistence;
import java.sql.Connection;
import java.sql.DriverManager;
public class LedgerDataSource {
// Single writer endpoint -- failover is transparent
private static final String WRITER_URL =
"jdbc:postgresql://nbi-ledger.cluster-abcdef.ap-south-1.rds.amazonaws.com:5432/ledger";
public Connection getConnection() throws Exception {
return DriverManager.getConnection(WRITER_URL, "admin", getRotatedPassword());
}
private String getRotatedPassword() {
// Fetched from Secrets Manager at runtime
return "fetched-at-runtime";
}
}
What are read replicas?
Read replicas are about handling more reads. A read replica is a separate, readable database instance that receives changes asynchronously from the primary. Because it is asynchronous, the replica can be slightly behind the primary, which is called replication lag. You direct read-only traffic -- reports, analytics, dashboards -- to the replica's own endpoint.
// With read replicas, the app routes writes and reads to DIFFERENT endpoints
package com.bank.persistence;
import java.sql.Connection;
import java.sql.DriverManager;
public class ReadWriteRouter {
private static final String WRITER = "jdbc:postgresql://nbi-ledger.rds.amazonaws.com:5432/ledger";
private static final String READER = "jdbc:postgresql://nbi-ledger-ro.rds.amazonaws.com:5432/ledger";
public Connection writerConnection() throws Exception {
return DriverManager.getConnection(WRITER, "admin", getPassword());
}
public Connection readerConnection() throws Exception {
return DriverManager.getConnection(READER, "admin", getPassword());
}
private String getPassword() { return "fetched-at-runtime"; }
}
How does Multi-AZ failover work?
On failure of the primary, RDS flips the single endpoint's DNS to the standby and promotes it, usually in one to two minutes. The application reconnects to the same endpoint automatically. Because the standby was synchronously replicated, there is zero data loss.
// Failover-resilient connection with retry logic
package com.bank.persistence;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class FailoverResilientConnection {
private static final String ENDPOINT =
"jdbc:postgresql://nbi-ledger.rds.amazonaws.com:5432/ledger";
public Connection getConnectionWithRetry() throws Exception {
int maxRetries = 3;
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try {
return DriverManager.getConnection(ENDPOINT, "admin", "password");
} catch (SQLException e) {
System.out.println("Connection attempt " + attempt + " failed, retrying...");
Thread.sleep(5000 * attempt); // exponential backoff
}
}
throw new RuntimeException("Failed to connect after " + maxRetries + " attempts");
}
}
How is read replica promotion different from Multi-AZ failover?
A read replica does not fail over automatically. Promoting it is a deliberate manual action: you call promote-read-replica, which breaks the replication link and makes the replica a standalone primary. This is a recovery action, not a transparent failover. After promotion, the old replication relationship is gone and must be re-established.
# Manual promotion of a read replica (deliberate recovery action)
aws rds promote-read-replica --db-instance-identifier nbi-ledger-replica-1
# This breaks the replication link permanently
# The promoted instance becomes a standalone writer
// After promotion, the application must be reconfigured to point to the new writer
package com.bank.persistence;
public class ReplicaPromotionHandler {
public static void onPromotion(String newWriterEndpoint) {
System.out.println("ALERT: Read replica promoted to standalone writer");
System.out.println("New writer endpoint: " + newWriterEndpoint);
System.out.println("Old replication link is permanently broken");
System.out.println("Action: update application config and create new replicas");
}
}
Why must read-after-write consistency come from the primary?
Because replicas are asynchronous, there is replication lag. If you update a balance on the primary and immediately read it from a replica, the replica may not have received the write yet, returning stale data. This is a critical issue for banking operations where confirming a balance after a transfer must be accurate.
// Wrong: reading a just-updated balance from a replica
package com.bank.service;
import java.math.BigDecimal;
public class TransferService {
private final ReadWriteRouter router = new ReadWriteRouter();
public BigDecimal transferAndConfirm(String fromAccount, BigDecimal amount) throws Exception {
// Write: debit the account on the primary
try (var conn = router.writerConnection()) {
// UPDATE accounts SET balance = balance - amount WHERE id = fromAccount
}
// WRONG: reading from replica may return stale (pre-debit) balance
// try (var conn = router.readerConnection()) { ... }
// CORRECT: read-after-write must come from the primary
try (var conn = router.writerConnection()) {
// SELECT balance FROM accounts WHERE id = fromAccount
return BigDecimal.ZERO; // placeholder
}
}
}
How do you use both together in production?
A production banking database typically has both: Multi-AZ for availability and one or more read replicas for read scaling. The primary handles writes and consistency-critical reads. The replicas absorb heavy read traffic like reports and dashboards. Multi-AZ ensures the primary survives an Availability Zone failure.
// Production routing strategy
package com.bank.persistence;
public class ProductionRoutingStrategy {
public String route(String operation, boolean requiresConsistency) {
if (operation.equals("WRITE")) {
return "PRIMARY (Multi-AZ protected)";
}
if (requiresConsistency) {
return "PRIMARY (read-after-write consistency)";
}
return "READ REPLICA (offload heavy reads)";
}
}
How does Aurora blur the line?
Aurora replicas are both readable and fast-failover targets. Aurora stores data in a shared distributed storage layer replicated six ways across three Availability Zones, and Aurora replicas read from the same storage. This means an Aurora replica can fail over in seconds rather than minutes, and its replication lag is typically single-digit milliseconds. Cross-Region read replicas additionally serve disaster recovery and low-latency local reads.
// Aurora reader endpoint automatically distributes reads across replicas
package com.bank.persistence;
public class AuroraConnectionConfig {
// Writer endpoint for writes and consistency-critical reads
private static final String WRITER =
"jdbc:postgresql://nbi-ledger.cluster-abcdef.ap-south-1.rds.amazonaws.com:5432/ledger";
// Reader endpoint: Aurora distributes across up to 15 replicas
private static final String READER =
"jdbc:postgresql://nbi-ledger.cluster-ro-abcdef.ap-south-1.rds.amazonaws.com:5432/ledger";
public void explain() {
System.out.println("Aurora replicas: readable AND fast-failover targets");
System.out.println("Shared storage: 6 copies across 3 AZs");
System.out.println("Failover: seconds, not minutes");
System.out.println("Lag: typically single-digit milliseconds");
}
}
What are the key differences at a glance?
| Feature | Multi-AZ | Read Replica |
|---|---|---|
| Purpose | High availability | Read scaling |
| Replication | Synchronous | Asynchronous |
| Readable | No | Yes |
| Failover | Automatic, same endpoint | Manual promotion |
| Data loss on failover | Zero | Possible (lag) |
| Cross-Region | No (same Region) | Yes |
| Cost | ~2x primary | Additional instance |
package com.bank.infrastructure;
public class MultiAzVsReplicaSummary {
public static void main(String[] args) {
System.out.println("Multi-AZ: AVAILABILITY via synchronous standby");
System.out.println(" - Automatic failover, same endpoint, zero data loss");
System.out.println(" - Standby is NOT readable");
System.out.println();
System.out.println("Read Replica: PERFORMANCE via async copy");
System.out.println(" - Readable for reports and dashboards");
System.out.println(" - Manual promotion, possible data loss");
System.out.println(" - Can be cross-Region for DR");
}
}
Visual Overview
RDS Multi-AZ (Synchronous Standby)
┌──────────────────┐ ┌──────────────────┐
│ Primary (AZ-a) │ sync │ Standby (AZ-b) │
│ │────────→│ │
│ Writes + Reads │ write │ NOT readable │
│ │ ack'd │ Takes over on │
│ nbi-ledger.rds │ after │ primary failure │
│ .amazonaws.com │ BOTH │ │
└────────┬─────────┘ persist └──────────────────┘
│ ▲
│ │ automatic
│ failover: │ DNS flip
│ same endpoint ──┘
│ 1-2 minutes
▼ zero data loss
┌──────────────────┐
│ Application │
│ (single endpoint│
│ for R + W) │
└──────────────────┘
RDS Read Replicas (Asynchronous Copy)
┌──────────────────┐ async ┌──────────────────┐
│ Primary │─────────→│ Read Replica 1 │
│ (writes + critical│ lag │ (reports, │
│ reads) │ │ dashboards) │
└──────────────────┘ └──────────────────┘
│ async ┌──────────────────┐
└───────────────────→│ Read Replica 2 │
│ (analytics) │
└──────────────────┘
Application routes:
WRITE + read-after-write → Primary endpoint
Heavy read-only traffic → Reader endpoint
Key Takeaway
RDS Multi-AZ and read replicas solve two completely different problems. Multi-AZ is about availability. When I enable it, RDS keeps a synchronous standby in a second Availability Zone, and every committed write goes to both the primary and the standby before it is acknowledged, so the standby is always perfectly current. That standby is not readable -- it exists only to take over. If the primary fails, RDS automatically fails over to the standby behind the same endpoint in a minute or two with zero data loss.
Read replicas are about performance, specifically scaling reads. A read replica is a separate, readable instance that receives changes asynchronously from the primary, so it can be slightly behind. I point heavy read-only traffic like reports and dashboards at the replica's endpoint so the primary is left free for writes and latency-sensitive reads. A read replica does not fail over automatically; promoting it is a deliberate manual action that breaks its replication link.
The contrast that matters most is the failover behavior and the consistency guarantee. Multi-AZ failover is automatic and transparent on the same endpoint. Read replica promotion is manual. And because replicas are asynchronous, I must never serve a read-after-write from a replica when the value must be perfectly current -- if I just updated a balance, I read that from the primary.
At National Bank of India I ran the ledger with both features together. Multi-AZ gave me automatic failover so an Availability Zone outage promoted the synchronous standby in about ninety seconds with zero data loss. Two read replicas absorbed the month-end reporting load so live transfers stayed fast. I explicitly routed consistency-critical reads to the primary, because once a developer read a just-updated balance from a lagging replica and saw a stale value.
Remember one sentence: Multi-AZ is a synchronous hidden standby for automatic failover with zero data loss, read replicas are asynchronous copies for read scaling, and production databases use both together.
---