Users far from the primary region get slow responses
“The app is snappy in us-east, but users in Sydney see 1-2 second page loads; every request makes several sequential database round trips across an ocean.”
THE PRINCIPLE
Move data to where it is read, keep conversations short where it is written, and choose the consistency you pay for per operation.
FIRST MOVES
- Trace one slow request from the far region: count sequential cross-region round trips. Collapsing ten round trips to one usually beats any new infrastructure.
- Put the app tier next to its data, not next to users, unless the data comes too; a regional app calling a remote database is often slower than one remote call.
- Serve cacheable responses from the edge (CDN with s-maxage / stale-while-revalidate) and public, rarely changing data from regional read replicas.
- Keep writes on one primary and give remote regions local reads; after a user's own write, route their reads to the primary or wait for the replica (e.g. Aurora write forwarding SESSION mode).
- Only go multi-writer if users own region-local data or you accept conflict resolution (DynamoDB global tables MREC is last-writer-wins); synchronous multi-region consistency costs write latency.
TOOLS: THEN → NOW
One region, everyone pays the round tripEdge caching plus cross-region read replicas (Aurora Global Database, DynamoDB global tables, Postgres streaming replicas)
Multi-master everywhere for speedSingle primary per data set or per user's home region; multi-region strong consistency only where RPO 0 is required
PATTERN SNAPSHOT
// Read-your-writes: pin a user to the primary briefly after they write.
const PIN_SECONDS = 5; // above replica lag p99 (Aurora ReplicaLag, pg replay lag)
function dbFor(session: Session, mustBeFresh = false) {
return mustBeFresh || session.cookie("pin_primary") ? primary : localReplica;
}
async function renameUser(session: Session, name: string) {
await primary.query("UPDATE users SET name = $2 WHERE id = $1", [session.userId, name]);
session.setCookie("pin_primary", "1", { maxAgeSeconds: PIN_SECONDS });
}
// Most reads stay local; balances and checkout pass mustBeFresh = true.
const user = await dbFor(session).query("SELECT * FROM users WHERE id = $1", [session.userId]);CLOSE THE AI. EXPLAIN THIS.
A page makes 8 sequential queries and the primary is 150 ms away. What is the latency floor, and which three changes reduce it most?HOW IT WORKS UNDERNEATH
RELATED SYMPTOMS
SOURCES
Guide reviewed