Read Replicas & Replication
Read replicas are copies of the primary database that receive writes via replication and serve read queries, offloading read traffic from the primary.
Read replicas = photocopies of the boss's notebook. They're slightly outdated, but 100 interns can read copies simultaneously instead of lining up at the boss's desk.
Asynchronous replication means replicas lag behind the primary by milliseconds to seconds. Applications reading from replicas must tolerate stale data. For reads that require fresh data (e.g., after a write), route to the primary or use synchronous replication with the performance penalty accepted. Replication lag monitoring is critical — lag spikes during high write throughput or replica rebuilds. Multi-region replication enables disaster recovery and reduces read latency for geographically distributed users.
PostgreSQL streaming replication uses the WAL (Write-Ahead Log): the primary ships WAL segments to replicas which replay them. Synchronous replication waits for at least one replica to acknowledge before the primary commits — zero data loss but +1 network RTT on every write. Semi-synchronous (MySQL) waits only for the replica to receive the WAL, not apply it. For failover, automated tools like Patroni (PostgreSQL) manage leader election using etcd or Consul as a distributed coordination layer. Read-after-write consistency (reading your own writes immediately) requires routing that user's reads to the primary for a short window post-write or using a monotonic read token. Aurora PostgreSQL achieves sub-10ms replica lag by sharing storage across compute nodes rather than shipping WAL.
I'd add read replicas as the first scaling step for read-heavy workloads. I'd explicitly handle replica lag: route reads requiring freshness (e.g., immediately after a write) to the primary using a read-your-writes routing layer. I'd monitor replication lag with alerts at 1s and circuit-break at 10s. For cross-region reads, I'd accept eventual consistency and design the UI to reflect that (e.g., 'feed may take a moment to update').
Routing all reads to replicas including reads that follow a write. This causes read-your-own-writes failures where a user creates an item and immediately doesn't see it. Maintain a primary-read window post-write or use session consistency routing.