⚖️ What Is a Load Balancer?
A load balancer sits in front of your application. It receives incoming traffic and spreads it across multiple backend servers instead of sending everything to one place.
🌍 Users → ⚖️ Load Balancer → 💻 EC2 Instances (Backend)<div class="infographic-lb">
<style>
.infographic-lb {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--lane-0: #1a1a1a;
--lane-1: #1f9d55;
--lane-2: #2563eb;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
max-width: 880px;
margin: 0 auto;
padding: clamp(1.25rem, 5vw, 3rem);
box-sizing: border-box;
line-height: 1.5;
}
.infographic-lb[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--lane-0: #d8d5cd;
--lane-1: #4ade80;
--lane-2: #5b8def;
}
.infographic-lb * { box-sizing: border-box; }
.lb-title {
font-family: var(--display-font); font-size: clamp(1.4rem, 3.6vw, 1.9rem);
margin: 0 0 1.5rem; line-height: 1.15; text-align: center;
}
/* controls */
.lb-controls {
display: flex; gap: 0.75rem; align-items: center; justify-content: center;
margin-bottom: 1.75rem;
}
.lb-ctrl-btn {
width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
background: var(--accent); color: #fff; border: none; cursor: pointer; padding: 0; border-radius: 2px;
}
.lb-ctrl-btn.lb-restart { background: none; color: var(--ink-soft); border: 1px solid var(--line); }
.lb-ctrl-btn svg { width: 16px; height: 16px; }
.lb-ctrl-btn .icon-pause { display: none; }
.lb-ctrl-btn.is-running .icon-play { display: none; }
.lb-ctrl-btn.is-running .icon-pause { display: block; }
/* diagram */
.lb-diagram { width: 100%; height: auto; overflow: visible; }
.lb-guide-solid { stroke-width: 2; fill: none; stroke-dasharray: 3 5; }
.lb-guide-dashed { stroke-width: 2; stroke-dasharray: 3 5; fill: none; }
.lb-guide-flow { animation: lb-flow 0.7s linear infinite; animation-play-state: paused; }
.infographic-lb.is-active .lb-guide-flow { animation-play-state: running; }
@keyframes lb-flow { to { stroke-dashoffset: -16; } }
.lb-request-arrow { opacity: 0; }
.lb-server-box { fill: var(--paper-alt); stroke: var(--line); stroke-width: 1.5; transition: stroke 0.25s; }
.lb-server-box.is-hit { stroke-width: 2.5; }
.lb-server-pin { stroke: var(--ink-soft); stroke-width: 2; }
.lb-lb-box { fill: var(--paper-alt); stroke: var(--ink); stroke-width: 2; }
.lb-hub-line { stroke: var(--accent); stroke-width: 2; fill: none; }
.lb-hub-dot { fill: var(--paper); stroke: var(--accent); stroke-width: 2; }
.lb-node-label { font-family: var(--body-font); font-size: 12px; font-weight: 600; fill: var(--ink); }
.lb-lb-label { font-family: var(--body-font); font-size: 13px; font-weight: 600; fill: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-lb *, .infographic-lb *::before, .infographic-lb *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<div class="lb-controls">
<button type="button" class="lb-ctrl-btn lb-toggle" aria-label="Play or pause">
<svg class="icon-play" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
<svg class="icon-pause" viewBox="0 0 24 24" fill="currentColor"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>
</button>
<button type="button" class="lb-ctrl-btn lb-restart" aria-label="Restart">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M1 4v6h6"/><path d="M3.5 15a9 9 0 1 0 2-9.5L1 10"/></svg>
</button>
</div>
<svg class="lb-diagram" viewBox="0 0 880 460" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Three colored request lanes flowing from users through a load balancer to their servers and back, shown as paired directional arrows">
<defs>
<marker id="arrow-lane0" 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" fill="var(--lane-0)" />
</marker>
<marker id="arrow-lane1" 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" fill="var(--lane-1)" />
</marker>
<marker id="arrow-lane2" 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" fill="var(--lane-2)" />
</marker>
</defs>
<!-- paired directional guide arrows: top line = request (rightward), bottom line = response (leftward) -->
<g>
<!-- lane 0 -->
<path class="lb-guide-solid lb-guide-flow" stroke="var(--lane-0)" opacity="0.55" marker-end="url(#arrow-lane0)" d="M 92 83 L 366 83" />
<path class="lb-guide-solid lb-guide-flow" stroke="var(--lane-0)" opacity="0.55" marker-end="url(#arrow-lane0)" d="M 366 97 L 92 97" />
<path class="lb-guide-dashed lb-guide-flow" stroke="var(--lane-0)" opacity="0.55" marker-end="url(#arrow-lane0)" d="M 524 83 L 766 83" />
<path class="lb-guide-dashed lb-guide-flow" stroke="var(--lane-0)" opacity="0.55" marker-end="url(#arrow-lane0)" d="M 766 97 L 524 97" />
<!-- lane 1 -->
<path class="lb-guide-solid lb-guide-flow" stroke="var(--lane-1)" opacity="0.55" marker-end="url(#arrow-lane1)" d="M 92 223 L 366 223" />
<path class="lb-guide-solid lb-guide-flow" stroke="var(--lane-1)" opacity="0.55" marker-end="url(#arrow-lane1)" d="M 366 237 L 92 237" />
<path class="lb-guide-dashed lb-guide-flow" stroke="var(--lane-1)" opacity="0.55" marker-end="url(#arrow-lane1)" d="M 524 223 L 766 223" />
<path class="lb-guide-dashed lb-guide-flow" stroke="var(--lane-1)" opacity="0.55" marker-end="url(#arrow-lane1)" d="M 766 237 L 524 237" />
<!-- lane 2 -->
<path class="lb-guide-solid lb-guide-flow" stroke="var(--lane-2)" opacity="0.55" marker-end="url(#arrow-lane2)" d="M 92 363 L 366 363" />
<path class="lb-guide-solid lb-guide-flow" stroke="var(--lane-2)" opacity="0.55" marker-end="url(#arrow-lane2)" d="M 366 377 L 92 377" />
<path class="lb-guide-dashed lb-guide-flow" stroke="var(--lane-2)" opacity="0.55" marker-end="url(#arrow-lane2)" d="M 524 363 L 766 363" />
<path class="lb-guide-dashed lb-guide-flow" stroke="var(--lane-2)" opacity="0.55" marker-end="url(#arrow-lane2)" d="M 766 377 L 524 377" />
</g>
<!-- users -->
<g>
<g transform="translate(60,90)">
<circle cy="-9" r="10" fill="var(--lane-0)" />
<path d="M -19 22 C -19 3, 19 3, 19 22 L 19 27 L -19 27 Z" fill="var(--lane-0)" />
</g>
<text class="lb-node-label" x="60" y="132" text-anchor="middle">User 1</text>
<g transform="translate(60,230)">
<circle cy="-9" r="10" fill="var(--lane-1)" />
<path d="M -19 22 C -19 3, 19 3, 19 22 L 19 27 L -19 27 Z" fill="var(--lane-1)" />
</g>
<text class="lb-node-label" x="60" y="272" text-anchor="middle">User 2</text>
<g transform="translate(60,370)">
<circle cy="-9" r="10" fill="var(--lane-2)" />
<path d="M -19 22 C -19 3, 19 3, 19 22 L 19 27 L -19 27 Z" fill="var(--lane-2)" />
</g>
<text class="lb-node-label" x="60" y="412" text-anchor="middle">User 3</text>
</g>
<!-- load balancer -->
<g>
<rect class="lb-lb-box" x="370" y="50" width="150" height="360" rx="14" />
<text class="lb-lb-label" x="445" y="38" text-anchor="middle">Load Balancer</text>
<g transform="translate(445,230)">
<circle class="lb-hub-dot" r="17" />
<line class="lb-hub-line" x1="14" y1="-7" x2="42" y2="-28" />
<line class="lb-hub-line" x1="17" y1="0" x2="48" y2="0" />
<line class="lb-hub-line" x1="14" y1="7" x2="42" y2="28" />
<circle class="lb-hub-dot" cx="46" cy="-28" r="6" />
<circle class="lb-hub-dot" cx="52" cy="0" r="6" />
<circle class="lb-hub-dot" cx="46" cy="28" r="6" />
</g>
</g>
<!-- servers -->
<g id="server-0">
<g transform="translate(800,90)">
<line class="lb-server-pin" x1="-10" y1="-28" x2="-10" y2="-22"/><line class="lb-server-pin" x1="0" y1="-28" x2="0" y2="-22"/><line class="lb-server-pin" x1="10" y1="-28" x2="10" y2="-22"/>
<line class="lb-server-pin" x1="-10" y1="28" x2="-10" y2="22"/><line class="lb-server-pin" x1="0" y1="28" x2="0" y2="22"/><line class="lb-server-pin" x1="10" y1="28" x2="10" y2="22"/>
<line class="lb-server-pin" x1="-28" y1="-10" x2="-22" y2="-10"/><line class="lb-server-pin" x1="-28" y1="10" x2="-22" y2="10"/>
<line class="lb-server-pin" x1="28" y1="-10" x2="22" y2="-10"/><line class="lb-server-pin" x1="28" y1="10" x2="22" y2="10"/>
<rect class="lb-server-box" x="-22" y="-22" width="44" height="44" rx="3" />
</g>
<text class="lb-node-label" x="800" y="146" text-anchor="middle">Instance 1</text>
</g>
<g id="server-1">
<g transform="translate(800,230)">
<line class="lb-server-pin" x1="-10" y1="-28" x2="-10" y2="-22"/><line class="lb-server-pin" x1="0" y1="-28" x2="0" y2="-22"/><line class="lb-server-pin" x1="10" y1="-28" x2="10" y2="-22"/>
<line class="lb-server-pin" x1="-10" y1="28" x2="-10" y2="22"/><line class="lb-server-pin" x1="0" y1="28" x2="0" y2="22"/><line class="lb-server-pin" x1="10" y1="28" x2="10" y2="22"/>
<line class="lb-server-pin" x1="-28" y1="-10" x2="-22" y2="-10"/><line class="lb-server-pin" x1="-28" y1="10" x2="-22" y2="10"/>
<line class="lb-server-pin" x1="28" y1="-10" x2="22" y2="-10"/><line class="lb-server-pin" x1="28" y1="10" x2="22" y2="10"/>
<rect class="lb-server-box" x="-22" y="-22" width="44" height="44" rx="3" />
</g>
<text class="lb-node-label" x="800" y="286" text-anchor="middle">Instance 2</text>
</g>
<g id="server-2">
<g transform="translate(800,370)">
<line class="lb-server-pin" x1="-10" y1="-28" x2="-10" y2="-22"/><line class="lb-server-pin" x1="0" y1="-28" x2="0" y2="-22"/><line class="lb-server-pin" x1="10" y1="-28" x2="10" y2="-22"/>
<line class="lb-server-pin" x1="-10" y1="28" x2="-10" y2="22"/><line class="lb-server-pin" x1="0" y1="28" x2="0" y2="22"/><line class="lb-server-pin" x1="10" y1="28" x2="10" y2="22"/>
<line class="lb-server-pin" x1="-28" y1="-10" x2="-22" y2="-10"/><line class="lb-server-pin" x1="-28" y1="10" x2="-22" y2="10"/>
<line class="lb-server-pin" x1="28" y1="-10" x2="22" y2="-10"/><line class="lb-server-pin" x1="28" y1="10" x2="22" y2="10"/>
<rect class="lb-server-box" x="-22" y="-22" width="44" height="44" rx="3" />
</g>
<text class="lb-node-label" x="800" y="426" text-anchor="middle">Instance 3</text>
</g>
<!-- moving request arrows, one per lane, small triangles that flip direction -->
<polygon class="lb-request-arrow" id="dot-0" points="-8,-5 8,0 -8,5" fill="var(--lane-0)" />
<polygon class="lb-request-arrow" id="dot-1" points="-8,-5 8,0 -8,5" fill="var(--lane-1)" />
<polygon class="lb-request-arrow" id="dot-2" points="-8,-5 8,0 -8,5" fill="var(--lane-2)" />
</svg>
</div>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-lb')
|| document.querySelector('.infographic-lb');
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 reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var toggleBtn = wrapper.querySelector('.lb-toggle');
var restartBtn = wrapper.querySelector('.lb-restart');
var arrows = [
wrapper.querySelector('#dot-0'),
wrapper.querySelector('#dot-1'),
wrapper.querySelector('#dot-2')
];
var serverBoxes = [
wrapper.querySelector('#server-0 .lb-server-box'),
wrapper.querySelector('#server-1 .lb-server-box'),
wrapper.querySelector('#server-2 .lb-server-box')
];
var laneColors = ['var(--lane-0)', 'var(--lane-1)', 'var(--lane-2)'];
var rowY = [90, 230, 370];
var userX = 92, lbLeft = 366, lbRight = 524, serverX = 766;
var isRunning = false;
var runToken = 0;
function setArrow(el, x, y, angleDeg) {
el.setAttribute('transform', 'translate(' + x + ',' + y + ') rotate(' + angleDeg + ')');
}
function delay(ms) { return new Promise(function (res) { setTimeout(res, ms); }); }
function waitIfPaused() {
return new Promise(function (resolve) {
(function check() {
if (isRunning) resolve(); else setTimeout(check, 150);
})();
});
}
function animate(el, fromX, toX, y, angleDeg, durationMs) {
return new Promise(function (resolve) {
if (reduceMotion) {
setArrow(el, toX, y, angleDeg);
resolve();
return;
}
var start = null;
function frame(ts) {
if (!start) start = ts;
var t = Math.min(1, (ts - start) / durationMs);
var x = fromX + (toX - fromX) * t;
setArrow(el, x, y, angleDeg);
if (t < 1) requestAnimationFrame(frame); else resolve();
}
requestAnimationFrame(frame);
});
}
function flashServer(idx) {
var box = serverBoxes[idx];
box.classList.add('is-hit');
box.style.stroke = laneColors[idx];
setTimeout(function () { box.classList.remove('is-hit'); }, 350);
}
async function laneCycle(idx, myToken, initialDelay) {
await delay(initialDelay);
var yFwd = rowY[idx] - 7;
var yBack = rowY[idx] + 7;
var el = arrows[idx];
while (myToken === runToken) {
await waitIfPaused();
if (myToken !== runToken) return;
setArrow(el, userX, yFwd, 0);
el.setAttribute('opacity', 1);
await animate(el, userX, lbLeft, yFwd, 0, 500);
await animate(el, lbLeft, lbRight, yFwd, 0, 350);
await animate(el, lbRight, serverX - 26, yFwd, 0, 500);
el.setAttribute('opacity', 0);
flashServer(idx);
await delay(350);
if (myToken !== runToken) return;
setArrow(el, serverX - 26, yBack, 180);
el.setAttribute('opacity', 1);
await animate(el, serverX - 26, lbRight, yBack, 180, 500);
await animate(el, lbRight, lbLeft, yBack, 180, 350);
await animate(el, lbLeft, userX, yBack, 180, 500);
el.setAttribute('opacity', 0);
await delay(500 + idx * 250);
}
}
function startLoops() {
runToken += 1;
var myToken = runToken;
laneCycle(0, myToken, 0);
laneCycle(1, myToken, 300);
laneCycle(2, myToken, 600);
}
toggleBtn.addEventListener('click', function () {
isRunning = !isRunning;
toggleBtn.classList.toggle('is-running', isRunning);
wrapper.classList.toggle('is-active', isRunning && !reduceMotion);
});
restartBtn.addEventListener('click', function () {
arrows.forEach(function (a) { a.setAttribute('opacity', 0); });
serverBoxes.forEach(function (b) { b.classList.remove('is-hit'); });
isRunning = true;
toggleBtn.classList.add('is-running');
wrapper.classList.toggle('is-active', !reduceMotion);
startLoops();
});
startLoops();
})();
</script>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});✅ Result: no single server gets overwhelmed. Traffic is spread evenly, which improves both performance and scalability.
🧐 Why Use One?
🎯 Core benefits
⚖️ Spreads traffic across multiple EC2 instances
🌐 Gives users one single access point (a DNS name), even though many servers sit behind it
🛡️ Detects failures automatically and stops sending traffic to unhealthy instances
❤️ Runs regular health checks on each instance
🔒 Can handle HTTPS decryption for you (SSL termination)
🌍 Can span multiple Availability Zones, so an entire AZ going down doesn't take your app with it
🧠 The core idea
Without a load balancer: one server = one bottleneck ❌, and one point of failure.
With a load balancer: many servers share the load = a scalable, resilient system ✅.
🧮 It's a Managed Service
An AWS Elastic Load Balancer (ELB) is fully managed by AWS:
✅ AWS guarantees it keeps running
🔧 AWS handles upgrades, patching, and high availability behind the scenes
🎛️ You only get a limited set of configuration options — by design, so there's less for you to manage
💡 You could build and run your own load balancer on EC2. It would be cheaper to set up, but you'd be responsible for all the maintenance and integration work yourself. For most use cases, ELB is easier and safer.
🚨 Exam framing: AWS ELB is the preferred answer over "build it yourself," unless the question specifically calls for a custom setup
⚖️ Types of Load Balancers
A. Application Load Balancer (ALB) — Layer 7
Works at the HTTP/HTTPS level, so it understands the content of requests, not just the packets.
✨ Features
🌐 Supports HTTP, HTTPS, and gRPC
🧭 Advanced routing based on the request itself:
Path-based (e.g.
/apivs/images)Host-based (different domains routed differently)
🎯 Best for: web applications, microservices — anywhere routing decisions depend on the request content.
B. Network Load Balancer (NLB) — Layer 4
Works at the TCP/UDP level. It doesn't inspect request content — it just moves packets, extremely fast.
✨ Features
🚀 Very high performance, capable of handling millions of requests per second
📍 Provides a static IP (via Elastic IP) — useful when clients need a fixed address to connect to
🎯 Best for: real-time systems, gaming 🎮, financial apps 💹 — anywhere raw speed and low latency matter most.
C. Gateway Load Balancer (GWLB) — Layer 3
Designed to route traffic through third-party security appliances before it reaches your app.
🔍 What it does
🔥 Firewalling
🚨 Intrusion detection
🧬 Deep packet inspection
📊 How it works
🌍 User → GWLB → 🔥 Firewall (EC2) → GWLB → 💻 ApplicationTraffic is inspected before it's allowed to reach your application. GWLB uses the GENEVE protocol to pass traffic to and from these security appliances.
✅ Exam keyword: security, firewall, packet inspection
D. Classic Load Balancer (CLB) — Deprecated
❌ Legacy load balancer, officially retired in 2023
Mixed Layer 4 and Layer 7 behavior in one product
Replaced by ALB 🟦 and NLB 🟥 — you won't need to set one up today, but it may still show up in exam questions as the "old" option
🤝 Quick Comparison
Feature | 🟦 ALB | 🟥 NLB | 🟩 GWLB |
|---|---|---|---|
OSI Layer | 7 | 4 | 3 |
Protocols | HTTP / HTTPS / gRPC 🌐 | TCP / UDP ⚡ | IP (GENEVE) 🧬 |
Performance | High | Ultra-high 🚀 | High |
Static IP | ❌ | ✅ | ❌ |
Best for | Web apps, microservices | High-performance, low-latency apps | Security appliances (firewalls, IDS) |
<div class="infographic-lbtypes">
<style>
.infographic-lbtypes {
--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', system-ui, sans-serif;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
max-width: 960px;
margin: 0 auto;
padding: clamp(1.25rem, 5vw, 3rem);
box-sizing: border-box;
line-height: 1.5;
}
.infographic-lbtypes[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.infographic-lbtypes * { box-sizing: border-box; }
.lbt-title {
font-family: var(--display-font); font-size: clamp(1.4rem, 3.6vw, 1.9rem);
margin: 0 0 1.25rem; line-height: 1.15; text-align: center;
}
.lbt-controls {
display: flex; gap: 0.75rem; align-items: center; justify-content: center;
margin-bottom: 2rem;
}
.lbt-ctrl-btn {
width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
background: var(--accent); color: #fff; border: none; cursor: pointer; padding: 0; border-radius: 2px;
}
.lbt-ctrl-btn.lbt-restart { background: none; color: var(--ink-soft); border: 1px solid var(--line); }
.lbt-ctrl-btn svg { width: 16px; height: 16px; }
.lbt-ctrl-btn .icon-pause { display: none; }
.lbt-ctrl-btn.is-running .icon-play { display: none; }
.lbt-ctrl-btn.is-running .icon-pause { display: block; }
.lbt-grid {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
background: var(--line); border: 1px solid var(--line);
}
.lbt-col {
background: var(--paper); padding: 1.5rem 1.25rem; cursor: pointer;
border-top: 3px solid transparent; transition: background 0.15s, border-color 0.15s, opacity 0.2s;
}
.lbt-col.is-highlighted { background: var(--accent-soft); border-top-color: var(--accent); }
.lbt-grid.has-highlight .lbt-col:not(.is-highlighted) { opacity: 0.45; }
.lbt-col-head { display: flex; flex-direction: column; align-items: center; text-align: center; margin-bottom: 1rem; }
.lbt-col-head svg { width: 64px; height: 64px; margin-bottom: 0.6rem; }
.lbt-col-name { font-family: var(--display-font); font-size: 1.3rem; font-weight: 600; }
.lbt-col-full { font-size: 0.78rem; color: var(--ink-soft); }
.lbt-tags { display: flex; gap: 0.4rem; justify-content: center; flex-wrap: wrap; margin-bottom: 1rem; }
.lbt-tag {
font-size: 0.72rem; font-weight: 600; color: var(--accent); background: var(--accent-soft);
padding: 0.25rem 0.55rem; border-radius: 2px; white-space: nowrap;
}
.lbt-points { list-style: none; margin: 0 0 1.25rem; padding: 0; }
.lbt-points li {
position: relative; padding-left: 0.9rem; font-size: 0.8rem; color: var(--ink-soft);
margin-bottom: 0.4rem; line-height: 1.4;
}
.lbt-points li::before {
content: ""; position: absolute; left: 0; top: 0.5em; width: 5px; height: 5px;
background: var(--accent); border-radius: 50%;
}
.lbt-points li strong { color: var(--ink); }
.lbt-flow { width: 100%; height: auto; overflow: visible; }
.lbt-flow-line { stroke-width: 2; fill: none; stroke-dasharray: 3 5; }
.lbt-flow-line.lbt-anim { animation: lbt-flow 0.7s linear infinite; animation-play-state: paused; }
.infographic-lbtypes.is-active .lbt-flow-line.lbt-anim { animation-play-state: running; }
@keyframes lbt-flow { to { stroke-dashoffset: -16; } }
.lbt-node-label { font-family: var(--body-font); font-size: 10px; fill: var(--ink-soft); }
.lbt-hub-ring { fill: var(--paper-alt); stroke: var(--accent); stroke-width: 2; }
.lbt-icon-mark { stroke: var(--accent); stroke-width: 2; fill: none; }
.lbt-instance { fill: var(--paper-alt); stroke: var(--ink-soft); stroke-width: 1.5; }
.lbt-person path, .lbt-person circle { fill: var(--ink-soft); }
@media (max-width: 700px) {
.lbt-grid { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
.infographic-lbtypes *, .infographic-lbtypes *::before, .infographic-lbtypes *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<h2 class="lbt-title">Load Balancer Types and Comparision</h2>
<div class="lbt-controls">
<button type="button" class="lbt-ctrl-btn lbt-toggle" aria-label="Play or pause">
<svg class="icon-play" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
<svg class="icon-pause" viewBox="0 0 24 24" fill="currentColor"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>
</button>
<button type="button" class="lbt-ctrl-btn lbt-restart" aria-label="Restart">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M1 4v6h6"/><path d="M3.5 15a9 9 0 1 0 2-9.5L1 10"/></svg>
</button>
</div>
<div class="lbt-grid">
<!-- ALB -->
<div class="lbt-col" data-col="alb">
<div class="lbt-col-head">
<svg viewBox="0 0 64 64">
<circle class="lbt-hub-ring" cx="32" cy="32" r="29" />
<rect class="lbt-icon-mark" x="26" y="14" width="12" height="9" rx="1.5" />
<line class="lbt-icon-mark" x1="32" y1="23" x2="32" y2="30" />
<line class="lbt-icon-mark" x1="20" y1="30" x2="44" y2="30" />
<line class="lbt-icon-mark" x1="20" y1="30" x2="20" y2="36" />
<line class="lbt-icon-mark" x1="32" y1="30" x2="32" y2="36" />
<line class="lbt-icon-mark" x1="44" y1="30" x2="44" y2="36" />
<rect class="lbt-icon-mark" x="15" y="36" width="10" height="8" rx="1.5" />
<rect class="lbt-icon-mark" x="27" y="36" width="10" height="8" rx="1.5" />
<rect class="lbt-icon-mark" x="39" y="36" width="10" height="8" rx="1.5" />
</svg>
<div class="lbt-col-name">ALB</div>
<div class="lbt-col-full">Application Load Balancer</div>
</div>
<div class="lbt-tags">
<span class="lbt-tag">Layer 7</span>
<span class="lbt-tag">HTTP / HTTPS / gRPC</span>
</div>
<ul class="lbt-points">
<li><strong>HTTP / HTTPS / gRPC</strong> protocols (Layer 7)</li>
<li><strong>HTTP Routing</strong> features</li>
<li><strong>Static DNS</strong> (URL)</li>
</ul>
<svg class="lbt-flow" viewBox="0 0 260 170">
<defs>
<marker id="arrow-alb" 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" fill="var(--accent)" />
</marker>
</defs>
<g class="lbt-person" transform="translate(26,85)">
<circle cy="-8" r="7" />
<path d="M -13 15 C -13 2, 13 2, 13 15 L 13 19 L -13 19 Z" />
</g>
<text class="lbt-node-label" x="26" y="118" text-anchor="middle">Users</text>
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-alb)" d="M 42 85 L 106 85" />
<circle class="lbt-hub-ring" cx="130" cy="85" r="24" />
<rect class="lbt-icon-mark" x="124" y="70" width="12" height="8" rx="1.5" />
<line class="lbt-icon-mark" x1="130" y1="78" x2="130" y2="84" />
<line class="lbt-icon-mark" x1="119" y1="84" x2="141" y2="84" />
<line class="lbt-icon-mark" x1="119" y1="84" x2="119" y2="90" />
<line class="lbt-icon-mark" x1="141" y1="84" x2="141" y2="90" />
<rect class="lbt-icon-mark" x="113" y="90" width="12" height="7" rx="1.5" />
<rect class="lbt-icon-mark" x="135" y="90" width="12" height="7" rx="1.5" />
<text class="lbt-node-label" x="130" y="119" text-anchor="middle">ALB</text>
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-alb)" d="M 154 85 L 210 40" />
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-alb)" d="M 154 85 L 210 85" />
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-alb)" d="M 154 85 L 210 130" />
<g transform="translate(228,40)"><rect class="lbt-instance" x="-11" y="-11" width="22" height="22" rx="2"/></g>
<g transform="translate(228,85)"><rect class="lbt-instance" x="-11" y="-11" width="22" height="22" rx="2"/></g>
<g transform="translate(228,130)"><rect class="lbt-instance" x="-11" y="-11" width="22" height="22" rx="2"/></g>
<text class="lbt-node-label" x="228" y="152" text-anchor="middle">Instances</text>
</svg>
</div>
<!-- NLB -->
<div class="lbt-col" data-col="nlb">
<div class="lbt-col-head">
<svg viewBox="0 0 64 64">
<circle class="lbt-hub-ring" cx="32" cy="32" r="29" />
<rect class="lbt-icon-mark" x="14" y="27" width="10" height="10" rx="1.5" />
<line class="lbt-icon-mark" x1="24" y1="32" x2="34" y2="20" />
<line class="lbt-icon-mark" x1="24" y1="32" x2="34" y2="32" />
<line class="lbt-icon-mark" x1="24" y1="32" x2="34" y2="44" />
<rect class="lbt-icon-mark" x="36" y="15" width="8" height="8" rx="1.5" />
<rect class="lbt-icon-mark" x="36" y="28" width="8" height="8" rx="1.5" />
<rect class="lbt-icon-mark" x="36" y="41" width="8" height="8" rx="1.5" />
</svg>
<div class="lbt-col-name">NLB</div>
<div class="lbt-col-full">Network Load Balancer</div>
</div>
<div class="lbt-tags">
<span class="lbt-tag">Layer 4</span>
<span class="lbt-tag">TCP / UDP</span>
</div>
<ul class="lbt-points">
<li><strong>TCP / UDP</strong> protocols (Layer 4)</li>
<li><strong>High Performance:</strong> millions of requests per second</li>
<li><strong>Static IP</strong> through Elastic IP</li>
</ul>
<svg class="lbt-flow" viewBox="0 0 260 170">
<defs>
<marker id="arrow-nlb" 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" fill="var(--accent)" />
</marker>
</defs>
<g class="lbt-person" transform="translate(26,85)">
<circle cy="-8" r="7" />
<path d="M -13 15 C -13 2, 13 2, 13 15 L 13 19 L -13 19 Z" />
</g>
<text class="lbt-node-label" x="26" y="118" text-anchor="middle">Users</text>
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-nlb)" d="M 42 85 L 106 85" />
<circle class="lbt-hub-ring" cx="130" cy="85" r="24" />
<rect class="lbt-icon-mark" x="120" y="79" width="9" height="9" rx="1.5" />
<line class="lbt-icon-mark" x1="129" y1="83.5" x2="136" y2="76" />
<line class="lbt-icon-mark" x1="129" y1="83.5" x2="139" y2="83.5" />
<line class="lbt-icon-mark" x1="129" y1="83.5" x2="136" y2="91" />
<rect class="lbt-icon-mark" x="138" y="72" width="6" height="6" rx="1" />
<rect class="lbt-icon-mark" x="138" y="80.5" width="6" height="6" rx="1" />
<rect class="lbt-icon-mark" x="138" y="89" width="6" height="6" rx="1" />
<text class="lbt-node-label" x="130" y="119" text-anchor="middle">NLB</text>
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-nlb)" d="M 154 85 L 210 40" />
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-nlb)" d="M 154 85 L 210 85" />
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-nlb)" d="M 154 85 L 210 130" />
<g transform="translate(228,40)"><rect class="lbt-instance" x="-11" y="-11" width="22" height="22" rx="2"/></g>
<g transform="translate(228,85)"><rect class="lbt-instance" x="-11" y="-11" width="22" height="22" rx="2"/></g>
<g transform="translate(228,130)"><rect class="lbt-instance" x="-11" y="-11" width="22" height="22" rx="2"/></g>
<text class="lbt-node-label" x="228" y="152" text-anchor="middle">Instances</text>
</svg>
</div>
<!-- GWLB -->
<div class="lbt-col" data-col="gwlb">
<div class="lbt-col-head">
<svg viewBox="0 0 64 64">
<circle class="lbt-hub-ring" cx="32" cy="32" r="29" />
<line class="lbt-icon-mark" x1="14" y1="24" x2="24" y2="24" />
<line class="lbt-icon-mark" x1="18" y1="19" x2="14" y2="24" />
<line class="lbt-icon-mark" x1="18" y1="29" x2="14" y2="24" />
<line class="lbt-icon-mark" x1="24" y1="40" x2="14" y2="40" />
<line class="lbt-icon-mark" x1="20" y1="35" x2="24" y2="40" />
<line class="lbt-icon-mark" x1="20" y1="45" x2="24" y2="40" />
<rect class="lbt-icon-mark" x="36" y="17" width="7" height="7" rx="1" />
<rect class="lbt-icon-mark" x="46" y="17" width="7" height="7" rx="1" />
<rect class="lbt-icon-mark" x="36" y="30" width="7" height="7" rx="1" />
<rect class="lbt-icon-mark" x="46" y="30" width="7" height="7" rx="1" />
<rect class="lbt-icon-mark" x="36" y="43" width="7" height="7" rx="1" />
</svg>
<div class="lbt-col-name">GWLB</div>
<div class="lbt-col-full">Gateway Load Balancer</div>
</div>
<div class="lbt-tags">
<span class="lbt-tag">Layer 3</span>
<span class="lbt-tag">GENEVE</span>
</div>
<ul class="lbt-points">
<li><strong>GENEVE</strong> protocol on IP packets (Layer 3)</li>
<li>Route traffic to <strong>firewalls</strong> you manage on EC2 instances</li>
<li><strong>Intrusion detection</strong></li>
</ul>
<svg class="lbt-flow" viewBox="0 0 260 170">
<defs>
<marker id="arrow-gwlb" 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" fill="var(--accent)" />
</marker>
</defs>
<g class="lbt-person" transform="translate(26,50)">
<circle cy="-8" r="7" />
<path d="M -13 15 C -13 2, 13 2, 13 15 L 13 19 L -13 19 Z" />
</g>
<text class="lbt-node-label" x="26" y="83" text-anchor="middle">Users</text>
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-gwlb)" d="M 42 50 L 104 50" />
<circle class="lbt-hub-ring" cx="128" cy="50" r="22" />
<line class="lbt-icon-mark" x1="112" y1="42" x2="121" y2="42" />
<line class="lbt-icon-mark" x1="116" y1="38" x2="112" y2="42" />
<line class="lbt-icon-mark" x1="116" y1="46" x2="112" y2="42" />
<line class="lbt-icon-mark" x1="121" y1="58" x2="112" y2="58" />
<line class="lbt-icon-mark" x1="118" y1="54" x2="121" y2="58" />
<line class="lbt-icon-mark" x1="118" y1="62" x2="121" y2="58" />
<rect class="lbt-icon-mark" x="133" y="40" width="6" height="6" rx="1" />
<rect class="lbt-icon-mark" x="133" y="53" width="6" height="6" rx="1" />
<text class="lbt-node-label" x="150" y="70" text-anchor="start">GWLB</text>
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-gwlb)" d="M 150 50 L 208 50" />
<g transform="translate(226,50)"><rect class="lbt-instance" x="-11" y="-11" width="22" height="22" rx="2"/></g>
<text class="lbt-node-label" x="226" y="80" text-anchor="middle">Application</text>
<path class="lbt-flow-line lbt-anim" stroke="var(--accent)" opacity="0.7" marker-end="url(#arrow-gwlb)" d="M 128 72 L 128 118" />
<g transform="translate(128,138)">
<rect class="lbt-instance" x="-13" y="-13" width="26" height="26" rx="2"/>
<path class="lbt-icon-mark" d="M -6,-4 L 0,-7 L 6,-4 L 6,2 C 6,7 0,10 0,10 C 0,10 -6,7 -6,2 Z" stroke-width="1.5" />
</g>
<text class="lbt-node-label" x="128" y="163" text-anchor="middle">Security</text>
</svg>
</div>
</div>
</div>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-lbtypes')
|| document.querySelector('.infographic-lbtypes');
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 toggleBtn = wrapper.querySelector('.lbt-toggle');
var restartBtn = wrapper.querySelector('.lbt-restart');
var grid = wrapper.querySelector('.lbt-grid');
var cols = wrapper.querySelectorAll('.lbt-col');
var isRunning = true;
toggleBtn.classList.add('is-running');
wrapper.classList.add('is-active');
toggleBtn.addEventListener('click', function () {
isRunning = !isRunning;
toggleBtn.classList.toggle('is-running', isRunning);
wrapper.classList.toggle('is-active', isRunning);
});
restartBtn.addEventListener('click', function () {
isRunning = true;
toggleBtn.classList.add('is-running');
wrapper.classList.add('is-active');
});
cols.forEach(function (col) {
col.addEventListener('click', function () {
var already = col.classList.contains('is-highlighted');
cols.forEach(function (c) { c.classList.remove('is-highlighted'); });
if (!already) {
col.classList.add('is-highlighted');
grid.classList.add('has-highlight');
} else {
grid.classList.remove('has-highlight');
}
});
});
})();
</script>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});❓ How Load Balancers Enable Elasticity
A load balancer becomes really powerful when paired with an Auto Scaling Group ⚙️:
📈 As traffic increases, Auto Scaling adds new instances, and the load balancer starts routing traffic to them automatically
📉 As traffic decreases, Auto Scaling removes instances, and the load balancer stops sending traffic their way
This combination — load balancer + auto scaling — is what people mean when they talk about "elastic" cloud infrastructure: the system grows and shrinks with demand, without manual intervention.