ποΈ RDS Deployment Architectures
RDS offers different architectures for performance, high availability, and disaster recovery.
π‘ There's no single "best" architecture β it depends on your app's requirements.
π The Three Architectures
π Read Replicas β improve read performance
π Multi-AZ β improve high availability
π Multi-Region Read Replicas β improve global performance & disaster recovery
π 1. Amazon RDS Read Replicas
As your app grows, thousands of users browse, search, and view reports β all read operations. Eventually the primary database struggles to keep up.
π‘ A Read Replica is a copy of your primary database dedicated to handling reads, spreading the load instead of hitting one database every time.
ποΈ How It Works
<!-- Main RDS + Read Replicas + Application(s). Self-contained, drop into codeveda.dev. -->
<div class="infographic-rrep">
<header class="rrep-head">
<button class="rrep-run-btn" type="button">
<svg class="run-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg>
<span class="run-label">Run Flow</span>
</button>
</header>
<div class="rrep-canvas">
<svg viewBox="0 0 640 470" xmlns="http://www.w3.org/2000/svg" class="rrep-svg">
<defs>
<marker id="rrep-arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" class="arrow-fill"/>
</marker>
</defs>
<!-- replication connectors -->
<line id="rrep-line-repl-left" x1="255" y1="110" x2="185" y2="110" class="connector-line solid" marker-end="url(#rrep-arrow)"/>
<line id="rrep-line-repl-right" x1="395" y1="110" x2="465" y2="110" class="connector-line solid" marker-end="url(#rrep-arrow)"/>
<text x="220" y="98" text-anchor="middle" class="edge-label">replication</text>
<text x="430" y="98" text-anchor="middle" class="edge-label">replication</text>
<!-- read / write connectors -->
<line id="rrep-line-read-left" x1="110" y1="166" x2="110" y2="398" class="connector-line solid" marker-end="url(#rrep-arrow)"/>
<line id="rrep-line-read-main" x1="350" y1="166" x2="350" y2="398" class="connector-line solid" marker-end="url(#rrep-arrow)"/>
<line id="rrep-line-write" x1="300" y1="398" x2="300" y2="166" class="connector-line solid" marker-end="url(#rrep-arrow)"/>
<line id="rrep-line-read-right" x1="540" y1="166" x2="540" y2="398" class="connector-line solid" marker-end="url(#rrep-arrow)"/>
<text x="128" y="290" class="edge-label edge-label--read">read</text>
<text x="368" y="290" class="edge-label edge-label--read">read</text>
<text x="252" y="290" class="edge-label edge-label--write" text-anchor="end">writes</text>
<text x="558" y="290" class="edge-label edge-label--read">read</text>
<!-- motion paths (invisible) for the run animation -->
<path id="rrep-path-write" d="M300,398 L300,166" fill="none" stroke="none"/>
<path id="rrep-path-repl-left" d="M255,110 L185,110" fill="none" stroke="none"/>
<path id="rrep-path-repl-right" d="M395,110 L465,110" fill="none" stroke="none"/>
<path id="rrep-path-read-left" d="M110,166 L110,398" fill="none" stroke="none"/>
<path id="rrep-path-read-main" d="M350,166 L350,398" fill="none" stroke="none"/>
<path id="rrep-path-read-right" d="M540,166 L540,398" fill="none" stroke="none"/>
<!-- Left Read Replica -->
<g class="rrep-node" data-part="replica-left" tabindex="0" role="button" aria-label="Read Replica" aria-expanded="false">
<rect x="40" y="55" width="140" height="111" rx="12" class="node-shape"/>
<text x="110" y="80" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="110" y="96" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(93,105) scale(1.4)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="110" y="196" text-anchor="middle" class="node-label node-label--caption">Read Replica</text>
<!-- Main -->
<g class="rrep-node" data-part="main" tabindex="0" role="button" aria-label="Main RDS instance" aria-expanded="false">
<rect x="255" y="55" width="140" height="111" rx="12" class="node-shape"/>
<text x="325" y="80" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="325" y="96" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(308,105) scale(1.4)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="325" y="196" text-anchor="middle" class="node-label node-label--caption">Main</text>
<!-- Right Read Replica -->
<g class="rrep-node" data-part="replica-right" tabindex="0" role="button" aria-label="Read Replica" aria-expanded="false">
<rect x="470" y="55" width="140" height="111" rx="12" class="node-shape"/>
<text x="540" y="80" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="540" y="96" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(523,105) scale(1.4)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="540" y="196" text-anchor="middle" class="node-label node-label--caption">Read Replica</text>
<!-- Application(s) -->
<g class="rrep-node" data-part="app" tabindex="0" role="button" aria-label="Application(s)" aria-expanded="false">
<rect x="20" y="398" width="600" height="60" rx="8" class="node-shape"/>
<text x="320" y="434" text-anchor="middle" class="node-label">Application(s)</text>
</g>
<!-- pulses: one per motion path, each shown/hidden per phase -->
<circle r="7" class="rrep-pulse" id="rrep-pulse-write" opacity="0">
<animateMotion id="rrep-motion-write" dur="1.3s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#rrep-path-write"/></animateMotion>
</circle>
<circle r="7" class="rrep-pulse" id="rrep-pulse-repl-left" opacity="0">
<animateMotion id="rrep-motion-repl-left" dur="1.1s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#rrep-path-repl-left"/></animateMotion>
</circle>
<circle r="7" class="rrep-pulse" id="rrep-pulse-repl-right" opacity="0">
<animateMotion id="rrep-motion-repl-right" dur="1.1s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#rrep-path-repl-right"/></animateMotion>
</circle>
<circle r="7" class="rrep-pulse" id="rrep-pulse-read-left" opacity="0">
<animateMotion id="rrep-motion-read-left" dur="1.3s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#rrep-path-read-left"/></animateMotion>
</circle>
<circle r="7" class="rrep-pulse" id="rrep-pulse-read-main" opacity="0">
<animateMotion id="rrep-motion-read-main" dur="1.3s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#rrep-path-read-main"/></animateMotion>
</circle>
<circle r="7" class="rrep-pulse" id="rrep-pulse-read-right" opacity="0">
<animateMotion id="rrep-motion-read-right" dur="1.3s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#rrep-path-read-right"/></animateMotion>
</circle>
</svg>
</div>
</div>
<style>
.infographic-rrep {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-rrep[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.infographic-rrep * { box-sizing: border-box; }
.infographic-rrep .rrep-head {
text-align: center;
padding: 0.5rem clamp(1rem, 4vw, 2rem) 1rem;
}
.infographic-rrep .rrep-run-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: var(--accent);
color: var(--paper);
border: none;
border-radius: 999px;
padding: 0.55rem 1.3rem;
font-family: inherit;
font-size: 0.88rem;
font-weight: 600;
cursor: pointer;
transition: opacity 0.15s;
}
.infographic-rrep .rrep-run-btn:hover { opacity: 0.88; }
.infographic-rrep .rrep-run-btn:disabled { opacity: 0.5; cursor: default; }
.infographic-rrep .run-icon { width: 15px; height: 15px; }
.infographic-rrep .rrep-canvas { padding: 0 clamp(0.75rem, 3vw, 2rem) 1rem; }
.infographic-rrep .rrep-svg { width: 100%; height: auto; display: block; overflow: visible; }
.infographic-rrep .connector-line {
stroke: var(--line);
stroke-width: 1.5;
stroke-dasharray: 4 3;
}
.infographic-rrep .connector-line.solid { stroke-dasharray: none; }
.infographic-rrep .arrow-fill { fill: var(--ink-soft); }
.infographic-rrep .connector-line.is-flowing {
stroke: var(--accent);
stroke-width: 2.5;
stroke-dasharray: 6 4;
animation: rrep-flow 0.6s linear infinite;
}
@keyframes rrep-flow {
to { stroke-dashoffset: -20; }
}
.infographic-rrep .edge-label {
font-size: 12px;
fill: var(--ink-soft);
font-family: var(--body-font);
}
.infographic-rrep .edge-label--write {
fill: var(--accent);
font-weight: 600;
}
.infographic-rrep .edge-label--read {
fill: var(--ink-soft);
font-weight: 500;
}
.infographic-rrep .rrep-node { cursor: pointer; outline: none; }
.infographic-rrep .rrep-node .node-shape {
fill: var(--paper-alt);
stroke: var(--line);
stroke-width: 1.5;
transition: fill 0.15s, stroke 0.15s, opacity 0.15s;
}
.infographic-rrep .rrep-node.is-active .node-shape {
fill: var(--accent-soft);
stroke: var(--accent);
}
.infographic-rrep .rrep-svg.has-active .rrep-node:not(.is-active) { opacity: 0.45; }
.infographic-rrep .rrep-node:focus-visible .node-shape { stroke: var(--accent); stroke-width: 2.5; }
.infographic-rrep .rrep-pulse { fill: var(--accent); transition: opacity 0.2s; }
.infographic-rrep .node-icon { color: var(--accent); }
.infographic-rrep .node-label {
font-family: var(--display-font);
font-size: 16px;
font-weight: 500;
fill: var(--ink);
}
.infographic-rrep .node-label--sm { font-size: 13px; }
.infographic-rrep .node-label--caption { font-size: 15px; }
@media (prefers-reduced-motion: reduce) {
.infographic-rrep * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
</style>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-rrep')
|| document.querySelector('.infographic-rrep');
// --- dark mode detection (cookie / body attribute) ---
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var svg = wrapper.querySelector('.rrep-svg');
var nodes = wrapper.querySelectorAll('.rrep-node');
var runBtn = wrapper.querySelector('.rrep-run-btn');
var lines = {
write: wrapper.querySelector('#rrep-line-write'),
replLeft: wrapper.querySelector('#rrep-line-repl-left'),
replRight: wrapper.querySelector('#rrep-line-repl-right'),
readLeft: wrapper.querySelector('#rrep-line-read-left'),
readMain: wrapper.querySelector('#rrep-line-read-main'),
readRight: wrapper.querySelector('#rrep-line-read-right')
};
var pulses = {
write: wrapper.querySelector('#rrep-pulse-write'),
replLeft: wrapper.querySelector('#rrep-pulse-repl-left'),
replRight: wrapper.querySelector('#rrep-pulse-repl-right'),
readLeft: wrapper.querySelector('#rrep-pulse-read-left'),
readMain: wrapper.querySelector('#rrep-pulse-read-main'),
readRight: wrapper.querySelector('#rrep-pulse-read-right')
};
var motions = {
write: wrapper.querySelector('#rrep-motion-write'),
replLeft: wrapper.querySelector('#rrep-motion-repl-left'),
replRight: wrapper.querySelector('#rrep-motion-repl-right'),
readLeft: wrapper.querySelector('#rrep-motion-read-left'),
readMain: wrapper.querySelector('#rrep-motion-read-main'),
readRight: wrapper.querySelector('#rrep-motion-read-right')
};
function setActive(parts) {
var list = parts ? (Array.isArray(parts) ? parts : [parts]) : [];
nodes.forEach(function (n) {
var isMatch = list.indexOf(n.dataset.part) !== -1;
n.classList.toggle('is-active', isMatch);
n.setAttribute('aria-expanded', isMatch ? 'true' : 'false');
});
svg.classList.toggle('has-active', list.length > 0);
}
function setLine(key, on) { lines[key].classList.toggle('is-flowing', on); }
function toggleNode(node) {
var wasActive = node.classList.contains('is-active');
setActive(wasActive ? null : node.dataset.part);
}
nodes.forEach(function (node) {
node.addEventListener('click', function () { toggleNode(node); });
node.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleNode(node); }
});
});
function fire(key, dur) {
motions[key].setAttribute('dur', (dur / 1000) + 's');
pulses[key].setAttribute('opacity', reducedMotion ? '0' : '1');
try { motions[key].beginElement(); } catch (e) { /* Safari fallback: state highlights still play */ }
}
function hidePulse(key) { pulses[key].setAttribute('opacity', '0'); }
// --- Run Flow animation: write to Main, replicate out, then reads from all three ---
var speed = reducedMotion ? 0.35 : 1;
var writeDur = 1300 * speed;
var replDur = 1100 * speed;
var readDur = 1300 * speed;
var gap = 250 * speed;
var timers = [];
function after(ms, fn) { timers.push(setTimeout(fn, ms)); }
runBtn.addEventListener('click', function () {
timers.forEach(clearTimeout);
timers = [];
runBtn.disabled = true;
setActive(null);
Object.keys(lines).forEach(function (k) { setLine(k, false); });
var t = 0;
// Phase 1: write β only the app writes to Main
after(t, function () {
setActive('app');
setLine('write', true);
fire('write', writeDur);
});
after(t + writeDur, function () {
setActive('main');
setLine('write', false);
hidePulse('write');
});
t += writeDur + gap;
// Phase 2: replication β Main pushes to both read replicas
after(t, function () {
setActive('main');
setLine('replLeft', true);
setLine('replRight', true);
fire('replLeft', replDur);
fire('replRight', replDur);
});
after(t + replDur, function () {
setActive(['replica-left', 'replica-right']);
setLine('replLeft', false);
setLine('replRight', false);
hidePulse('replLeft');
hidePulse('replRight');
});
t += replDur + gap;
// Phase 3: reads β happen from Main AND both replicas
after(t, function () {
setActive(['replica-left', 'main', 'replica-right']);
setLine('readLeft', true);
setLine('readMain', true);
setLine('readRight', true);
fire('readLeft', readDur);
fire('readMain', readDur);
fire('readRight', readDur);
});
after(t + readDur, function () {
setActive('app');
setLine('readLeft', false);
setLine('readMain', false);
setLine('readRight', false);
hidePulse('readLeft');
hidePulse('readMain');
hidePulse('readRight');
});
t += readDur + gap;
// Reset
after(t, function () {
setActive(null);
runBtn.disabled = false;
});
});
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">π Reads β can come from the primary or any Read Replica
βοΈ Writes β always go to the primary; replicas auto-sync from it and can't be written to directly
π Benefits
Improves read performance
Distributes read traffic
Reduces load on the primary
Supports up to 15 Read Replicas
π Use When
Read-heavy traffic β many users browsing, dashboards, reports, high-traffic storefronts.
π― Exam tip: "Improve read performance" / "scale read traffic" β Read Replicas
π 2. Amazon RDS Multi-AZ Deployment
Read Replicas fix performance. Multi-AZ fixes availability.
If hardware fails, an AZ has an outage, or there's a network issue, your app goes down without a backup database β that's what Multi-AZ solves.
π‘ A Multi-AZ deployment keeps a standby copy of your primary DB in a different AZ, continuously synced but idle until needed.
<!-- Main RDS + Failover DB + Application(s). Self-contained, drop into codeveda.dev. -->
<div class="infographic-failover">
<header class="fo-head">
<button class="fo-run-btn" type="button">
<svg class="run-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg>
<span class="run-label">Run Flow</span>
</button>
</header>
<div class="fo-canvas">
<svg viewBox="0 0 640 430" xmlns="http://www.w3.org/2000/svg" class="fo-svg">
<defs>
<marker id="fo-arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" class="arrow-fill"/>
</marker>
<marker id="fo-arrow-dashed" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" class="arrow-fill-dashed"/>
</marker>
</defs>
<!-- replication connector -->
<line x1="180" y1="75" x2="465" y2="75" class="connector-line solid" marker-end="url(#fo-arrow)"/>
<text x="325" y="60" text-anchor="middle" class="edge-label">Replication <tspan class="edge-label--underline">cross AZ</tspan></text>
<!-- write / read connectors -->
<line id="fo-line-write" x1="90" y1="340" x2="90" y2="145" class="connector-line solid" marker-end="url(#fo-arrow)"/>
<line id="fo-line-read" x1="140" y1="145" x2="140" y2="340" class="connector-line solid" marker-end="url(#fo-arrow)"/>
<text x="70" y="248" text-anchor="end" class="edge-label edge-label--write">writes</text>
<text x="160" y="248" text-anchor="start" class="edge-label edge-label--read">read</text>
<!-- failover connector (dashed, elbowed) -->
<path id="fo-line-failover" d="M540,131 L540,380 L462,380" fill="none" class="connector-line dashed" marker-end="url(#fo-arrow-dashed)"/>
<text x="552" y="365" class="edge-label edge-label--sm">Failover in case of issues</text>
<text x="552" y="381" class="edge-label edge-label--sm">with Main DB</text>
<!-- motion paths (invisible) for the run animation -->
<path id="fo-motion-normal" d="M110,340 L110,75 L110,340" fill="none" stroke="none"/>
<path id="fo-motion-failover" d="M240,380 L462,380 L540,380 L540,75 L240,380" fill="none" stroke="none"/>
<!-- Main -->
<g class="fo-node" data-part="main" tabindex="0" role="button" aria-label="Main RDS instance" aria-expanded="false">
<rect x="40" y="20" width="140" height="111" rx="12" class="node-shape"/>
<text x="110" y="45" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="110" y="61" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(93,70) scale(1.4)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="110" y="161" text-anchor="middle" class="node-label node-label--caption">Main</text>
<!-- Failover DB -->
<g class="fo-node" data-part="failover" tabindex="0" role="button" aria-label="Failover DB" aria-expanded="false">
<rect x="470" y="20" width="140" height="111" rx="12" class="node-shape"/>
<text x="540" y="45" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="540" y="61" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(523,70) scale(1.4)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="540" y="161" text-anchor="middle" class="node-label node-label--caption">Failover DB</text>
<!-- Application(s) -->
<g class="fo-node" data-part="app" tabindex="0" role="button" aria-label="Application(s)" aria-expanded="false">
<rect x="20" y="340" width="440" height="80" rx="8" class="node-shape"/>
<text x="240" y="386" text-anchor="middle" class="node-label">Application(s)</text>
</g>
<!-- pulses (two separate dots β SVG combines multiple animateMotion on one element additively, so each phase gets its own) -->
<circle r="7" class="fo-pulse" id="fo-pulse-1" opacity="0">
<animateMotion id="fo-motion-1" dur="1.8s" begin="indefinite" fill="freeze" calcMode="linear" keyTimes="0;0.5;1">
<mpath href="#fo-motion-normal"/>
</animateMotion>
</circle>
<circle r="7" class="fo-pulse" id="fo-pulse-2" opacity="0">
<animateMotion id="fo-motion-2" dur="2.2s" begin="indefinite" fill="freeze" calcMode="linear" keyTimes="0;0.6;1">
<mpath href="#fo-motion-failover"/>
</animateMotion>
</circle>
</svg>
</div>
</div>
<style>
.infographic-failover {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--error: #c0392b;
--error-soft: #fbe9e7;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-failover[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--error: #e57373;
--error-soft: #3a2222;
}
.infographic-failover * { box-sizing: border-box; }
.infographic-failover .fo-head {
text-align: center;
padding: 0.5rem clamp(1rem, 4vw, 2rem) 1rem;
}
.infographic-failover .fo-run-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: var(--accent);
color: var(--paper);
border: none;
border-radius: 999px;
padding: 0.55rem 1.3rem;
font-family: inherit;
font-size: 0.88rem;
font-weight: 600;
cursor: pointer;
transition: opacity 0.15s;
}
.infographic-failover .fo-run-btn:hover { opacity: 0.88; }
.infographic-failover .fo-run-btn:disabled { opacity: 0.5; cursor: default; }
.infographic-failover .run-icon { width: 15px; height: 15px; }
.infographic-failover .fo-canvas { padding: 0 clamp(0.75rem, 3vw, 2rem) 1rem; }
.infographic-failover .fo-svg { width: 100%; height: auto; display: block; overflow: visible; }
.infographic-failover .connector-line {
stroke: var(--line);
stroke-width: 1.5;
fill: none;
}
.infographic-failover .connector-line.solid { stroke-dasharray: none; }
.infographic-failover .connector-line.dashed { stroke-dasharray: 5 4; }
.infographic-failover .connector-line.is-flowing {
stroke: var(--accent);
stroke-width: 2.5;
stroke-dasharray: 6 4;
animation: fo-flow 0.6s linear infinite;
}
@keyframes fo-flow {
to { stroke-dashoffset: -20; }
}
.infographic-failover .arrow-fill { fill: var(--ink-soft); }
.infographic-failover .arrow-fill-dashed { fill: var(--line); }
.infographic-failover .edge-label {
font-size: 13px;
fill: var(--ink);
font-family: var(--body-font);
}
.infographic-failover .edge-label--sm { font-size: 11.5px; fill: var(--ink-soft); }
.infographic-failover .edge-label--underline { text-decoration: underline; font-weight: 700; }
.infographic-failover .edge-label--write { fill: var(--accent); font-weight: 600; font-size: 14px; }
.infographic-failover .edge-label--read { fill: var(--ink-soft); font-weight: 500; font-size: 14px; }
.infographic-failover .fo-node { cursor: pointer; outline: none; }
.infographic-failover .fo-node .node-shape {
fill: var(--paper-alt);
stroke: var(--line);
stroke-width: 1.5;
transition: fill 0.15s, stroke 0.15s, opacity 0.15s;
}
.infographic-failover .fo-node.is-active .node-shape {
fill: var(--accent-soft);
stroke: var(--accent);
}
.infographic-failover .fo-node.is-failed .node-shape {
fill: var(--error-soft);
stroke: var(--error);
animation: fo-shake 0.4s;
}
@keyframes fo-shake {
0%, 100% { transform: translateX(0); }
20% { transform: translateX(-3px); }
40% { transform: translateX(3px); }
60% { transform: translateX(-2px); }
80% { transform: translateX(2px); }
}
.infographic-failover .fo-svg.has-active .fo-node:not(.is-active) { opacity: 0.45; }
.infographic-failover .fo-node:focus-visible .node-shape { stroke: var(--accent); stroke-width: 2.5; }
.infographic-failover .node-icon { color: var(--accent); }
.infographic-failover .node-label {
font-family: var(--display-font);
font-size: 16px;
font-weight: 500;
fill: var(--ink);
}
.infographic-failover .node-label--sm { font-size: 13px; }
.infographic-failover .node-label--caption { font-size: 15px; }
@media (prefers-reduced-motion: reduce) {
.infographic-failover * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
</style>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-failover')
|| document.querySelector('.infographic-failover');
// --- dark mode detection (cookie / body attribute) ---
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var svg = wrapper.querySelector('.fo-svg');
var nodes = wrapper.querySelectorAll('.fo-node');
var mainNode = wrapper.querySelector('.fo-node[data-part="main"]');
var runBtn = wrapper.querySelector('.fo-run-btn');
var pulse1 = wrapper.querySelector('#fo-pulse-1');
var pulse2 = wrapper.querySelector('#fo-pulse-2');
var motion1 = wrapper.querySelector('#fo-motion-1');
var motion2 = wrapper.querySelector('#fo-motion-2');
var lineWrite = wrapper.querySelector('#fo-line-write');
var lineRead = wrapper.querySelector('#fo-line-read');
var lineFailover = wrapper.querySelector('#fo-line-failover');
function setActive(part) {
nodes.forEach(function (n) {
var isMatch = part && n.dataset.part === part;
n.classList.toggle('is-active', isMatch);
n.setAttribute('aria-expanded', isMatch ? 'true' : 'false');
});
svg.classList.toggle('has-active', !!part);
}
function setLine(el, on) { el.classList.toggle('is-flowing', on); }
function toggleNode(node) {
var wasActive = node.classList.contains('is-active');
setActive(wasActive ? null : node.dataset.part);
}
nodes.forEach(function (node) {
node.addEventListener('click', function () { toggleNode(node); });
node.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleNode(node); }
});
});
// --- Run Flow animation: normal read/write on Main, then Main fails, then Failover DB takes over ---
var speed = reducedMotion ? 0.35 : 1;
var normalDur = 1800 * speed; // App <-> Main loop (write up, read down)
var normalReps = 2; // run the read/write loop twice to establish "normal operation"
var failurePause = 700 * speed; // Main flashes as failed
var failoverDur = 2200 * speed; // App <-> Failover DB loop (new normal via failover)
var failoverReps = 2;
var timers = [];
function after(ms, fn) { timers.push(setTimeout(fn, ms)); }
runBtn.addEventListener('click', function () {
timers.forEach(clearTimeout);
timers = [];
runBtn.disabled = true;
mainNode.classList.remove('is-failed');
setActive(null);
setLine(lineWrite, false);
setLine(lineRead, false);
setLine(lineFailover, false);
motion1.setAttribute('dur', (normalDur / 1000) + 's');
motion2.setAttribute('dur', (failoverDur / 1000) + 's');
var t = 0;
// Phase 1: normal reads/writes cycling between App and Main
for (var i = 0; i < normalReps; i++) {
(function (delay) {
after(delay, function () {
pulse1.setAttribute('opacity', reducedMotion ? '0' : '1');
try { motion1.beginElement(); } catch (e) { /* Safari fallback: state highlights still play */ }
setActive('app');
setLine(lineWrite, true);
setLine(lineRead, false);
});
after(delay + normalDur * 0.5, function () {
setActive('main');
setLine(lineWrite, false);
setLine(lineRead, true);
});
after(delay + normalDur, function () {
setActive('app');
setLine(lineRead, false);
pulse1.setAttribute('opacity', '0');
});
})(t);
t += normalDur + 120 * speed;
}
// Phase 2: Main fails
after(t, function () {
setActive('main');
mainNode.classList.add('is-failed');
});
t += failurePause;
// Phase 3: reroute + new normal operation via Failover DB
for (var j = 0; j < failoverReps; j++) {
(function (delay) {
after(delay, function () {
pulse2.setAttribute('opacity', reducedMotion ? '0' : '1');
try { motion2.beginElement(); } catch (e) { /* Safari fallback: state highlights still play */ }
setActive('app');
setLine(lineFailover, true);
});
after(delay + failoverDur * 0.6, function () { setActive('failover'); });
after(delay + failoverDur, function () {
setActive('app');
setLine(lineFailover, false);
pulse2.setAttribute('opacity', '0');
});
})(t);
t += failoverDur + 120 * speed;
}
// Reset
after(t + 50, function () {
setActive(null);
mainNode.classList.remove('is-failed');
runBtn.disabled = false;
});
});
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">π¨ On Failure
AWS automatically fails over β the standby becomes primary, and your app reconnects with minimal disruption. Fully managed by AWS.
β οΈ The standby is idle during normal operation β all reads and writes go to the primary. It only activates on failover.
π Benefits
High availability, automatic failover, better fault tolerance, improved disaster recovery within a Region.
π Key Points
Only one standby per deployment
Standby lives in a different AZ
Apps can't connect to the standby directly
Failover is fully automatic
π― Exam tip: "High availability" / "automatic failover" / "AZ outage" β Multi-AZ
π 3. Amazon RDS Multi-Region Read Replicas
Global users mean latency β a database in one Region is slow for users on the other side of the world. Multi-Region Read Replicas fix this by placing replicas closer to users.
Example:
Primary β Mumbai (
ap-south-1)Replica β Hyderabad (
ap-south-2)Replica β N. Virginia (
us-east-1)
<!-- Multi-Region RDS: Main + cross-region Read Replicas. Self-contained, drop into codeveda.dev. -->
<div class="infographic-mregion">
<header class="mr-head">
<button class="mr-run-btn" type="button">
<svg class="run-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg>
<span class="run-label">Run Flow</span>
</button>
</header>
<div class="mr-canvas">
<svg viewBox="0 0 1040 400" xmlns="http://www.w3.org/2000/svg" class="mr-svg">
<defs>
<marker id="mr-arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" class="arrow-fill"/>
</marker>
</defs>
<g transform="translate(0,70)">
<!-- region boundaries -->
<rect id="mr-region-1" x="8" y="10" width="292" height="290" rx="10" class="region-box"/>
<rect id="mr-region-2" x="370" y="10" width="292" height="290" rx="10" class="region-box"/>
<rect id="mr-region-3" x="732" y="10" width="292" height="290" rx="10" class="region-box"/>
<!-- region badges (sit above the region box, never touching its border) -->
<g class="region-badge"><rect x="20" y="-24" width="20" height="20" rx="4" class="badge-flag"/><g transform="translate(24,-20) scale(0.55)"><g stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" fill="none" class="badge-flag-icon"><path d="M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528"/></g></g><text x="48" y="-10" class="region-label">ap-south-2</text></g>
<g class="region-badge"><rect x="382" y="-24" width="20" height="20" rx="4" class="badge-flag"/><g transform="translate(386,-20) scale(0.55)"><g stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" fill="none" class="badge-flag-icon"><path d="M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528"/></g></g><text x="410" y="-10" class="region-label">ap-south-1</text></g>
<g class="region-badge"><rect x="744" y="-24" width="20" height="20" rx="4" class="badge-flag"/><g transform="translate(748,-20) scale(0.55)"><g stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" fill="none" class="badge-flag-icon"><path d="M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528"/></g></g><text x="772" y="-10" class="region-label">us-east-1</text></g>
<!-- replication connectors -->
<line id="mr-line-repl-left" x1="446" y1="80" x2="224" y2="80" class="connector-line solid" marker-end="url(#mr-arrow)"/>
<line id="mr-line-repl-right" x1="586" y1="80" x2="808" y2="80" class="connector-line solid" marker-end="url(#mr-arrow)"/>
<text x="335" y="68" text-anchor="middle" class="edge-label">replication</text>
<text x="697" y="68" text-anchor="middle" class="edge-label">replication</text>
<!-- local read connectors -->
<line id="mr-line-read-1" x1="154" y1="130" x2="154" y2="230" class="connector-line solid" marker-end="url(#mr-arrow)"/>
<line id="mr-line-read-2" x1="536" y1="132" x2="536" y2="230" class="connector-line solid" marker-end="url(#mr-arrow)"/>
<line id="mr-line-read-3" x1="878" y1="130" x2="878" y2="230" class="connector-line solid" marker-end="url(#mr-arrow)"/>
<text x="172" y="185" class="edge-label edge-label--read">read</text>
<text x="554" y="185" class="edge-label edge-label--read">read</text>
<text x="896" y="185" class="edge-label edge-label--read">read</text>
<!-- local write (Main only) -->
<line id="mr-line-write-local" x1="496" y1="230" x2="496" y2="132" class="connector-line solid" marker-end="url(#mr-arrow)"/>
<text x="478" y="185" text-anchor="end" class="edge-label edge-label--write">writes</text>
<!-- cross-region writes to primary -->
<line id="mr-line-write-1" x1="230" y1="230" x2="472" y2="132" class="connector-line solid write-line" marker-end="url(#mr-arrow)"/>
<line id="mr-line-write-3" x1="802" y1="230" x2="560" y2="132" class="connector-line solid write-line" marker-end="url(#mr-arrow)"/>
<text x="300" y="165" text-anchor="middle" class="edge-label edge-label--write">writes</text>
<text x="732" y="165" text-anchor="middle" class="edge-label edge-label--write">writes</text>
<!-- motion paths (invisible) for the run animation -->
<path id="mr-path-write-1" d="M230,230 L472,132" fill="none" stroke="none"/>
<path id="mr-path-write-local" d="M496,230 L496,132" fill="none" stroke="none"/>
<path id="mr-path-write-3" d="M802,230 L560,132" fill="none" stroke="none"/>
<path id="mr-path-repl-left" d="M446,80 L224,80" fill="none" stroke="none"/>
<path id="mr-path-repl-right" d="M586,80 L808,80" fill="none" stroke="none"/>
<path id="mr-path-read-1" d="M154,130 L154,230" fill="none" stroke="none"/>
<path id="mr-path-read-2" d="M536,132 L536,230" fill="none" stroke="none"/>
<path id="mr-path-read-3" d="M878,130 L878,230" fill="none" stroke="none"/>
<!-- Region 1: Read Replica -->
<g class="mr-node" data-part="rds-1" tabindex="0" role="button" aria-label="Read Replica in ap-south-2" aria-expanded="false">
<rect x="84" y="30" width="140" height="100" rx="12" class="node-shape"/>
<text x="154" y="53" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="154" y="69" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(137,78) scale(1.35)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="154" y="158" text-anchor="middle" class="node-label node-label--caption">Read Replica</text>
<!-- Region 2: Main -->
<g class="mr-node" data-part="rds-2" tabindex="0" role="button" aria-label="Main RDS instance in ap-south-1" aria-expanded="false">
<rect x="446" y="30" width="140" height="100" rx="12" class="node-shape"/>
<text x="516" y="53" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="516" y="69" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(499,78) scale(1.35)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="516" y="158" text-anchor="middle" class="node-label node-label--caption">Main</text>
<!-- Region 3: Read Replica -->
<g class="mr-node" data-part="rds-3" tabindex="0" role="button" aria-label="Read Replica in us-east-1" aria-expanded="false">
<rect x="808" y="30" width="140" height="100" rx="12" class="node-shape"/>
<text x="878" y="53" text-anchor="middle" class="node-label node-label--sm">Amazon</text>
<text x="878" y="69" text-anchor="middle" class="node-label node-label--sm">RDS</text>
<g transform="translate(861,78) scale(1.35)"><g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" class="node-icon"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></g></g>
</g>
<text x="878" y="158" text-anchor="middle" class="node-label node-label--caption">Read Replica</text>
<!-- Application(s) x3 -->
<g class="mr-node" data-part="app-1" tabindex="0" role="button" aria-label="Application(s) in ap-south-2" aria-expanded="false">
<rect x="24" y="230" width="260" height="55" rx="8" class="node-shape"/>
<text x="154" y="264" text-anchor="middle" class="node-label">Application(s)</text>
</g>
<g class="mr-node" data-part="app-2" tabindex="0" role="button" aria-label="Application(s) in ap-south-1" aria-expanded="false">
<rect x="386" y="230" width="260" height="55" rx="8" class="node-shape"/>
<text x="516" y="264" text-anchor="middle" class="node-label">Application(s)</text>
</g>
<g class="mr-node" data-part="app-3" tabindex="0" role="button" aria-label="Application(s) in us-east-1" aria-expanded="false">
<rect x="748" y="230" width="260" height="55" rx="8" class="node-shape"/>
<text x="878" y="264" text-anchor="middle" class="node-label">Application(s)</text>
</g>
<!-- outage badge (disaster-recovery phase) -->
<g id="mr-outage-badge" class="outage-badge" opacity="0">
<rect x="60" y="130" width="188" height="30" rx="15" class="outage-pill"/>
<text x="154" y="150" text-anchor="middle" class="outage-text">Region outage</text>
</g>
<!-- pulses -->
<circle r="7" class="mr-pulse" id="mr-pulse-write-1" opacity="0"><animateMotion id="mr-motion-write-1" dur="1.1s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-write-1"/></animateMotion></circle>
<circle r="7" class="mr-pulse" id="mr-pulse-write-local" opacity="0"><animateMotion id="mr-motion-write-local" dur="1.1s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-write-local"/></animateMotion></circle>
<circle r="7" class="mr-pulse" id="mr-pulse-write-3" opacity="0"><animateMotion id="mr-motion-write-3" dur="1.1s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-write-3"/></animateMotion></circle>
<circle r="7" class="mr-pulse" id="mr-pulse-repl-left" opacity="0"><animateMotion id="mr-motion-repl-left" dur="1.1s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-repl-left"/></animateMotion></circle>
<circle r="7" class="mr-pulse" id="mr-pulse-repl-right" opacity="0"><animateMotion id="mr-motion-repl-right" dur="1.1s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-repl-right"/></animateMotion></circle>
<circle r="7" class="mr-pulse" id="mr-pulse-read-1" opacity="0"><animateMotion id="mr-motion-read-1" dur="0.9s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-read-1"/></animateMotion></circle>
<circle r="7" class="mr-pulse" id="mr-pulse-read-2" opacity="0"><animateMotion id="mr-motion-read-2" dur="0.9s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-read-2"/></animateMotion></circle>
<circle r="7" class="mr-pulse" id="mr-pulse-read-3" opacity="0"><animateMotion id="mr-motion-read-3" dur="0.9s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#mr-path-read-3"/></animateMotion></circle>
</g>
</svg>
</div>
</div>
<style>
.infographic-mregion {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--error: #c0392b;
--error-soft: #fbe9e7;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
box-sizing: border-box;
max-width: 1040px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-mregion[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--error: #e57373;
--error-soft: #3a2222;
}
.infographic-mregion * { box-sizing: border-box; }
.infographic-mregion .mr-head {
text-align: center;
padding: 0.5rem clamp(1rem, 4vw, 2rem) 1rem;
}
.infographic-mregion .mr-run-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: var(--accent);
color: var(--paper);
border: none;
border-radius: 999px;
padding: 0.55rem 1.3rem;
font-family: inherit;
font-size: 0.88rem;
font-weight: 600;
cursor: pointer;
transition: opacity 0.15s;
}
.infographic-mregion .mr-run-btn:hover { opacity: 0.88; }
.infographic-mregion .mr-run-btn:disabled { opacity: 0.5; cursor: default; }
.infographic-mregion .run-icon { width: 15px; height: 15px; }
.infographic-mregion .mr-canvas { padding: 0.5rem clamp(0.75rem, 3vw, 2rem) 1rem; }
.infographic-mregion .mr-svg { width: 100%; height: auto; display: block; overflow: visible; }
.infographic-mregion .region-box {
fill: none;
stroke: var(--line);
stroke-width: 1.5;
stroke-dasharray: 5 4;
transition: stroke 0.2s, fill 0.2s;
}
.infographic-mregion .region-box.is-down {
stroke: var(--error);
fill: var(--error-soft);
opacity: 0.5;
}
.infographic-mregion .badge-flag { fill: var(--accent-soft); }
.infographic-mregion .badge-flag-icon { color: var(--accent); }
.infographic-mregion .region-label {
font-size: 12px;
font-weight: 600;
fill: var(--accent);
font-family: var(--body-font);
}
.infographic-mregion .connector-line {
stroke: var(--line);
stroke-width: 1.5;
}
.infographic-mregion .arrow-fill { fill: var(--ink-soft); }
.infographic-mregion .connector-line.is-flowing {
stroke: var(--accent);
stroke-width: 2.5;
stroke-dasharray: 6 4;
animation: mr-flow 0.6s linear infinite;
}
@keyframes mr-flow { to { stroke-dashoffset: -20; } }
.infographic-mregion .edge-label {
font-size: 12px;
fill: var(--ink-soft);
font-family: var(--body-font);
}
.infographic-mregion .edge-label--write { fill: var(--accent); font-weight: 600; }
.infographic-mregion .edge-label--read { fill: var(--ink-soft); font-weight: 500; }
.infographic-mregion .mr-node { cursor: pointer; outline: none; }
.infographic-mregion .mr-node .node-shape {
fill: var(--paper-alt);
stroke: var(--line);
stroke-width: 1.5;
transition: fill 0.15s, stroke 0.15s, opacity 0.15s;
}
.infographic-mregion .mr-node.is-active .node-shape {
fill: var(--accent-soft);
stroke: var(--accent);
}
.infographic-mregion .mr-node.is-failed .node-shape {
fill: var(--error-soft);
stroke: var(--error);
}
.infographic-mregion .mr-svg.has-active .mr-node:not(.is-active) { opacity: 0.45; }
.infographic-mregion .mr-node:focus-visible .node-shape { stroke: var(--accent); stroke-width: 2.5; }
.infographic-mregion .mr-pulse { fill: var(--accent); transition: opacity 0.2s; }
.infographic-mregion .node-icon { color: var(--accent); }
.infographic-mregion .node-label {
font-family: var(--display-font);
font-size: 15px;
font-weight: 500;
fill: var(--ink);
}
.infographic-mregion .node-label--sm { font-size: 12px; }
.infographic-mregion .node-label--caption { font-size: 14px; }
.infographic-mregion .outage-badge { transition: opacity 0.25s; }
.infographic-mregion .outage-pill { fill: var(--error); }
.infographic-mregion .outage-text {
fill: var(--paper);
font-family: var(--body-font);
font-size: 12px;
font-weight: 700;
text-anchor: middle;
}
@media (prefers-reduced-motion: reduce) {
.infographic-mregion * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
</style>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-mregion')
|| document.querySelector('.infographic-mregion');
// --- dark mode detection (cookie / body attribute) ---
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var svg = wrapper.querySelector('.mr-svg');
var nodes = wrapper.querySelectorAll('.mr-node');
var runBtn = wrapper.querySelector('.mr-run-btn');
var region1 = wrapper.querySelector('#mr-region-1');
var rds1 = wrapper.querySelector('.mr-node[data-part="rds-1"]');
var outageBadge = wrapper.querySelector('#mr-outage-badge');
var lines = {
write1: wrapper.querySelector('#mr-line-write-1'),
writeLocal: wrapper.querySelector('#mr-line-write-local'),
write3: wrapper.querySelector('#mr-line-write-3'),
replLeft: wrapper.querySelector('#mr-line-repl-left'),
replRight: wrapper.querySelector('#mr-line-repl-right'),
read1: wrapper.querySelector('#mr-line-read-1'),
read2: wrapper.querySelector('#mr-line-read-2'),
read3: wrapper.querySelector('#mr-line-read-3')
};
var pulses = {
write1: wrapper.querySelector('#mr-pulse-write-1'),
writeLocal: wrapper.querySelector('#mr-pulse-write-local'),
write3: wrapper.querySelector('#mr-pulse-write-3'),
replLeft: wrapper.querySelector('#mr-pulse-repl-left'),
replRight: wrapper.querySelector('#mr-pulse-repl-right'),
read1: wrapper.querySelector('#mr-pulse-read-1'),
read2: wrapper.querySelector('#mr-pulse-read-2'),
read3: wrapper.querySelector('#mr-pulse-read-3')
};
var motions = {
write1: wrapper.querySelector('#mr-motion-write-1'),
writeLocal: wrapper.querySelector('#mr-motion-write-local'),
write3: wrapper.querySelector('#mr-motion-write-3'),
replLeft: wrapper.querySelector('#mr-motion-repl-left'),
replRight: wrapper.querySelector('#mr-motion-repl-right'),
read1: wrapper.querySelector('#mr-motion-read-1'),
read2: wrapper.querySelector('#mr-motion-read-2'),
read3: wrapper.querySelector('#mr-motion-read-3')
};
function setActive(parts) {
var list = parts ? (Array.isArray(parts) ? parts : [parts]) : [];
nodes.forEach(function (n) {
var isMatch = list.indexOf(n.dataset.part) !== -1;
n.classList.toggle('is-active', isMatch);
n.setAttribute('aria-expanded', isMatch ? 'true' : 'false');
});
svg.classList.toggle('has-active', list.length > 0);
}
function setLine(key, on) { lines[key].classList.toggle('is-flowing', on); }
function fire(key, dur) {
motions[key].setAttribute('dur', (dur / 1000) + 's');
pulses[key].setAttribute('opacity', reducedMotion ? '0' : '1');
try { motions[key].beginElement(); } catch (e) { /* Safari fallback: state highlights still play */ }
}
function hidePulse(key) { pulses[key].setAttribute('opacity', '0'); }
function toggleNode(node) {
var wasActive = node.classList.contains('is-active');
setActive(wasActive ? null : node.dataset.part);
}
nodes.forEach(function (node) {
node.addEventListener('click', function () { toggleNode(node); });
node.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleNode(node); }
});
});
// --- Run Flow: writes always to primary -> replicate out -> local reads everywhere -> disaster recovery ---
var speed = reducedMotion ? 0.35 : 1;
var writeDur = 1100 * speed;
var replDur = 1100 * speed;
var readDur = 900 * speed;
var outageDur = 1400 * speed;
var gap = 250 * speed;
var timers = [];
function after(ms, fn) { timers.push(setTimeout(fn, ms)); }
runBtn.addEventListener('click', function () {
timers.forEach(clearTimeout);
timers = [];
runBtn.disabled = true;
setActive(null);
Object.keys(lines).forEach(function (k) { setLine(k, false); });
region1.classList.remove('is-down');
rds1.classList.remove('is-failed');
outageBadge.setAttribute('opacity', '0');
var t = 0;
// Phase 1: writes β every application's writes travel back to the primary Region
after(t, function () {
setActive(['app-1', 'app-2', 'app-3']);
setLine('write1', true);
setLine('writeLocal', true);
setLine('write3', true);
fire('write1', writeDur);
fire('writeLocal', writeDur);
fire('write3', writeDur);
});
after(t + writeDur, function () {
setActive('rds-2');
setLine('write1', false);
setLine('writeLocal', false);
setLine('write3', false);
hidePulse('write1'); hidePulse('writeLocal'); hidePulse('write3');
});
t += writeDur + gap;
// Phase 2: replication β Main pushes the update out to both regional replicas
after(t, function () {
setActive('rds-2');
setLine('replLeft', true);
setLine('replRight', true);
fire('replLeft', replDur);
fire('replRight', replDur);
});
after(t + replDur, function () {
setActive(['rds-1', 'rds-3']);
setLine('replLeft', false);
setLine('replRight', false);
hidePulse('replLeft'); hidePulse('replRight');
});
t += replDur + gap;
// Phase 3: local reads β every app reads from its own nearby Region only
after(t, function () {
setActive(['rds-1', 'rds-2', 'rds-3']);
setLine('read1', true);
setLine('read2', true);
setLine('read3', true);
fire('read1', readDur);
fire('read2', readDur);
fire('read3', readDur);
});
after(t + readDur, function () {
setActive(['app-1', 'app-2', 'app-3']);
setLine('read1', false);
setLine('read2', false);
setLine('read3', false);
hidePulse('read1'); hidePulse('read2'); hidePulse('read3');
});
t += readDur + gap;
// Phase 4: disaster recovery β one Region goes down, copies still live elsewhere
after(t, function () {
setActive(null);
region1.classList.add('is-down');
rds1.classList.add('is-failed');
outageBadge.setAttribute('opacity', '1');
setActive(['rds-2', 'rds-3']);
});
t += outageDur;
// Phase 4b: traffic keeps flowing through the two healthy regions
after(t, function () {
setActive(['app-2', 'app-3']);
setLine('writeLocal', true);
setLine('write3', true);
fire('writeLocal', writeDur);
fire('write3', writeDur);
});
after(t + writeDur, function () {
setActive('rds-2');
setLine('writeLocal', false);
setLine('write3', false);
hidePulse('writeLocal'); hidePulse('write3');
});
t += writeDur + gap;
after(t, function () {
setActive(['rds-2', 'rds-3']);
setLine('read2', true);
setLine('read3', true);
fire('read2', readDur);
fire('read3', readDur);
});
after(t + readDur, function () {
setActive(['app-2', 'app-3']);
setLine('read2', false);
setLine('read3', false);
hidePulse('read2'); hidePulse('read3');
});
t += readDur + gap;
after(t, function () {
region1.classList.remove('is-down');
rds1.classList.remove('is-failed');
outageBadge.setAttribute('opacity', '0');
});
t += gap;
// Reset
after(t, function () {
setActive(null);
runBtn.disabled = false;
});
});
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">π Why Use It
π Better performance β users read from the nearest replica, cutting latency
π‘οΈ Disaster recovery β a Region-wide outage still leaves copies elsewhere
β οΈ Reads are local, but writes always travel back to the primary Region.
π° Cross-Region replication adds network transfer costs β Multi-Region setups cost more than single-Region ones.
π― Exam tip: "Global users" / "lower cross-Region latency" / "Region-level disaster recovery" β Multi-Region Read Replicas
π Quick Comparison
Feature | π Read Replica | π Multi-AZ | π Multi-Region |
|---|---|---|---|
Purpose | Read performance | High availability | Global performance + DR |
Handles reads? | β | β | β |
Handles writes? | β | β | β |
Writes go to | Primary | Primary | Primary |
Auto failover? | β | β | β |
Different AZ? | Optional | β | N/A |
Different Region? | β | β | β |
Max replicas | Up to 15 | 1 standby | Varies |
π― Exam Tips Recap
π Read Replicas scale read workloads
βοΈ Writes always go to the primary, even with replicas in play
π Multi-AZ = high availability via a standby in another AZ
π AZ failure β AWS auto-fails-over to standby
π Multi-Region Read Replicas = global performance + disaster recovery
π° Cross-Region replication costs more than single-Region setups