ArchitectMind
  1. Home
  2. Tutorials
  3. Book 10 · Security, System Design & Solution Architecture
  4. Volume III
  5. Load Balancing
Book 10 · Volume III — Large-Scale & Distributed System Design · Topic 1.2

Load Balancing

Spreading requests across instances by health and real load

11 min readStage 4 · Production & architecture10 interview questions
Chapter
Chapter 1 — High-Traffic Systems
Prerequisites
Topic 1.1
You will be able to
Choose L4 vs L7 and LB placement, pick algorithms that react to real load, configure health checks, outlier ejection, draining and slow start, handle long-lived connections, and monitor load balance quality
Covers
Load balancing
On this page
  1. 1. Concept / Definition
  2. 2. Why It Exists
  3. 3. Core Concepts — Algorithms
  4. 4. How It Works Internally — L7 Balancing
  5. 4A. Deep Dive — Health Checking
  6. 4B. Deep Dive — Connection Management
  7. 4C. Deep Dive — Zones and Cross-Zone Balancing
  8. 4D. Deep Dive — Long-Lived Connections
  9. 4E. Deep Dive — LB Limits and Failure Modes
  10. 5. APIs / Features / Syntax
  11. 6. Practical Examples
  12. 7. Common Problems & Mistakes
  13. 8. Performance & Production Considerations
  14. 9. Architecture & Design Considerations
  15. 10. Interview Questions & Answers

1Concept / Definition

A load balancer distributes incoming connections or requests across a pool of backend instances so that no instance is overloaded, failed instances are avoided, and capacity can be added or removed transparently. Load balancing happens at the edge (internet-facing LBs), inside the platform (internal LBs, ingress) and increasingly in clients themselves (service mesh sidecars, gRPC client-side balancing).

Load balancing tiers — ShopNow
Figure 1 — Load balancing tiers — ShopNow
L4 vs L7 load balancing
Figure 2 — L4 vs L7 load balancing
VocabularyMeaning
Target / upstreamBackend instance receiving traffic
Outlier ejectionTemporarily removing a misbehaving target
DrainingLetting in-flight requests finish before removal
Slow startGradually ramping traffic to new targets
Table 1 — Terms

2Why It Exists

Without good balancingConsequence
Round robin with one slow podp99 dominated by that pod
No drainingDeploys drop in-flight requests
No slow startCold JVMs overwhelmed after scale-out
Sticky sessionsUneven load, painful scale-in
Table 2 — Why

3Core Concepts — Algorithms

Load-balancing algorithms
Figure 3 — Load-balancing algorithms
AlgorithmShopNow use
Least outstanding requestsALB for web/API tiers
Power of two choices + EWMAEnvoy/mesh between services
Consistent hash (ring hash)Routing to cache nodes by key
Round robinNLB flows (L4)
Table 3 — Algorithm per tier
p99 latency with one slow pod
Figure 4 — p99 latency with one slow pod

4How It Works Internally — L7 Balancing

StepDetail
Accept TLS connectionTerminate TLS (ACM certificate)
Parse HTTP requestHost, path, headers
Match listener rule/api/orders → orders target group
Choose targetAlgorithm over healthy targets
Reuse backend connectionKeep-alive / HTTP/2 pool
Record outcomePassive health, metrics
Table 4 — Per-request path

4ADeep Dive — Health Checking

TypeDetail
ActiveLB polls /health/ready every 5–10 s
PassiveObserve real traffic errors/latency
Outlier ejection (Envoy)5 consecutive 5xx → eject 30 s, max 20% ejected
Readiness vs livenessLB uses readiness; don't route before warm-up
Fail-openIf all targets unhealthy, ALB routes to all (avoid total blackout)
Table 5 — Keep sick targets out

4BDeep Dive — Connection Management

FeaturePurpose
Keep-alive / HTTP/2Avoid TCP+TLS setup per request
Deregistration delayDraining 30–60 s on scale-in/deploy
Slow startRamp new targets over 60 s (JIT warm-up)
Idle timeoutsAlign LB < backend keep-alive to avoid 502s
Max connections per targetProtect backends
Table 6 — Lifecycle

4CDeep Dive — Zones and Cross-Zone Balancing

SettingTrade-off
Cross-zone on (ALB default)Even load; cross-AZ data transfer
Zone-aware routing (mesh)Lower latency and cost; imbalance risk if zones uneven
Zonal shiftMove traffic away from impaired AZ quickly
GuidanceKeep equal capacity per AZ; prefer local zone with fallback
Table 7 — Topology awareness

4DDeep Dive — Long-Lived Connections

ProblemSolution
gRPC/HTTP2 pins one connection to one podClient-side balancing (xDS) or L7 per-request LB
WebSockets never rebalanceMax connection age; reconnect with jitter
New pods get no trafficConnection churn policies
Scale-in drops socketsGraceful close with reconnect hints
Table 8 — Balance requests, not just connections

4EDeep Dive — LB Limits and Failure Modes

IssueMitigation
LB capacity ramp (sudden 10× spike)Pre-warming requests/LCU reservation, NLB for extreme
LB as SPOFManaged multi-AZ LBs; DNS over multiple
Retry amplification at LBLimit retries; retry budgets (7.2)
Misrouted health (shallow)Readiness includes dependencies prudently
Table 9 — Balancers can fail too

5APIs / Features / Syntax

HCL
# ALB target group: least outstanding requests, slow start, draining, readiness checks
resource "aws_lb_target_group" "orders" {
  name                          = "orders-tg"
  port                          = 8080
  protocol                      = "HTTP"
  target_type                   = "ip"
  load_balancing_algorithm_type = "least_outstanding_requests"
  slow_start                    = 60
  deregistration_delay          = 30
  health_check {
    path                = "/actuator/health/readiness"
    interval            = 10
    healthy_threshold   = 2
    unhealthy_threshold = 3
    timeout             = 3
  }
}
YAML
# Envoy/Istio: P2C least-request with outlier ejection and zone-aware routing
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata: { name: inventory }
spec:
  host: inventory.prod.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      simple: LEAST_REQUEST
      localityLbSetting: { enabled: true }
    connectionPool:
      http: { http2MaxRequests: 2000, maxRequestsPerConnection: 1000 }
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 20
YAML
# Spring Boot 4: graceful shutdown + readiness so draining works with the LB
server:
  shutdown: graceful
spring:
  lifecycle:
    timeout-per-shutdown-phase: 25s
management:
  endpoint:
    health:
      probes: { enabled: true }
      group:
        readiness: { include: readinessState, db, redis }

6Practical Examples

6.1 Slow pod dominating p99

One order pod on a noisy node served requests in 800 ms. Round robin gave it 1/40 of traffic and p99 of 820 ms; least outstanding requests plus outlier ejection brought p99 to 150 ms.

6.2 Deploy errors

Each rolling deploy produced ~300 502s. Aligning deregistration delay (30 s), graceful shutdown (25 s) and readiness=false on SIGTERM eliminated them.

6.3 PayGrid gRPC imbalance

gRPC clients pinned HTTP/2 connections to a few pods after scale-out. Istio per-request balancing and max connection age of 5 min fixed the skew.

6.4 Worked example — idle timeouts

LayerTimeout
ALB idle60 s
Tomcat keep-alive75 s (> ALB)
Table 10 — Avoid 502s

6.5 Worked example — slow start

SettingEffect
60 s rampNew pods warm JIT gently
Table 11 — Cold start

6.6 Worked example — max ejection

SettingReason
20%Never eject most of the pool
Table 12 — Safety

6.7 Worked example — interview whiteboard

PromptAnswer outline
"How does load balancing work and which algorithm would you use?""L4 (connections, huge throughput, static IPs) vs L7 (requests, routing, TLS). Placement: edge LB, ingress, client-side/mesh. Algorithms: round robin fails with uneven pods; least outstanding / P2C / EWMA follow real load; consistent hash for affinity. Health: readiness checks + passive outlier ejection with max %. Lifecycle: keep-alive, draining, slow start, aligned idle timeouts. Zone-aware with equal AZ capacity. Long-lived connections need per-request or client-side balancing. Monitor per-target load and errors."
Table 13 — Structured answer

6.8 Worked example — NovaBank internal

ChoiceReason
Internal NLB → EnvoymTLS end to end
Table 14 — Security + balancing

6.9 Worked example — anti-patterns

Anti-patternEffect
Sticky sessions for convenienceUneven load
Liveness as LB healthRouting to not-ready pods
Unlimited retries at LBAmplification
Cross-zone off with uneven AZsHot zone
Table 15 — Common mistakes

6.10 Worked example — consistent hash

UseDetail
Route by cartId to cache podsCache affinity
Table 16 — Affinity without stickiness

6.11 Worked example — weighted targets

Instance typeWeight
c7g.2xlarge2
c7g.xlarge1
Table 17 — Heterogeneous fleet

6.12 Worked example — zonal shift

EventAction
AZ-b degradedARC zonal shift away 1 h
Table 18 — AZ incidents

6.13 Worked example — NLB for extreme load

CaseReason
Sale-day 1M connectionsNLB scales instantly
Table 19 — Capacity

6.14 Worked example — TLS

PatternDetail
Terminate at ALB, re-encrypt to podsCompliance
Table 20 — Encryption

6.15 Worked example — WebSockets

SettingValue
Max connection age30 min + jitter
Table 21 — Rebalancing

6.16 Worked example — interview follow-ups

Follow-upAnswer
"Why not round robin?"Ignores real load; slow pods hurt p99
"What is P2C?"Pick two random targets, choose less loaded
Table 22 — Common probes

6.17 Worked example — checklist

Item✔
L4/L7 choice✔
Load-aware algorithm✔
Readiness + ejection✔
Draining + slow start✔
Timeouts aligned✔
Per-target metrics✔
Table 23 — LB baseline

6.18 Worked example — metrics

MetricAlert
Max/mean requests per target > 1.5Imbalance
Table 24 — Observability

6.19 Worked example — retries

SettingValue
Mesh retry on 503 once, budget 10%Bounded
Table 25 — Resilience

6.20 Worked example — client-side LB

ToolUse
Spring Cloud LoadBalancer / gRPC xDSNo central LB hop
Table 26 — Fewer hops

6.21 Worked example — interview scenario

QuestionAnswer
"New pods get no traffic after scale-out"Long-lived connections — per-request LB, connection age
Table 27 — Diagnose

6.22 Worked example — GWLB

UseDetail
Inline firewall appliancesTransparent insertion
Table 28 — Security appliances

6.23 Worked example — health path

PathContent
/actuator/health/readinessApp + critical deps
Table 29 — Readiness design

6.24 Worked example — LB capacity

MetricWatch
ALB LCUsPre-warm before sale
Table 30 — Limits

6.25 Worked example — cost

ChoiceImpact
Zone-aware routing−40% cross-AZ transfer
Table 31 — Economics

6.26 Worked example — documentation

ServiceAlgorithmHealth
ordersLORreadiness, 10 s
Table 32 — Clarity

7Common Problems & Mistakes

MistakeFix
Round robin everywhereLoad-aware
No drainingGraceful shutdown
Sticky sessionsStateless
Connection pinningPer-request LB
Table 33 — Mistakes and fixes

The classic mistakes are defaults left unexamined. Round robin is used everywhere even though pods differ in speed, so one slow instance sets the whole service's tail latency. Liveness endpoints are wired as load balancer health checks, so pods receive traffic before they are ready, or stay in rotation when a critical dependency fails. Sticky sessions are added for convenience and then make load uneven and scale-in painful, when moving session state to Redis would make the tier stateless. Long-lived gRPC and WebSocket connections pin traffic to old pods after scaling. And retries configured at the balancer, the mesh and the client multiply into a retry storm, turning a partial failure into a full outage.

8Performance & Production Considerations

ConsiderationPractice
Imbalance ratioMonitor
5xx by targetEject
Deploy error rateZero goal
Table 34 — Operating LBs

Operate the balancer as a production system in its own right. Dashboards should show requests and errors per target, not just totals, so an imbalance ratio above about 1.5, or one target with high 5xx, is visible immediately. Rolling deploys should produce zero errors; any non-zero count usually means draining, graceful shutdown and readiness are misaligned. Managed balancers scale gradually, so pre-warm or reserve capacity before a sale-day spike, or use NLB for sudden extreme load. Watch cross-zone data transfer too: zone-aware routing cut ShopNow's cross-AZ cost by about 40 percent, but it only works with equal capacity per zone. Rehearse zonal shift so traffic can leave an impaired zone within minutes.

9Architecture & Design Considerations

GuidelineDetail
Balance on real loadLOR, P2C
Eject fast, ramp slowOutliers, slow start
Right layerL4 edge, L7 routing
Table 35 — Design guidance

10Interview Questions & Answers

Q1BasicConcept

What does a load balancer do?

A load balancer spreads incoming connections or requests across a pool of backend instances, so no single instance is overloaded and the pool behaves like one reliable service. It also hides failures, by health-checking targets and routing only to those that are ready; enables scaling, because instances can be added or removed without clients noticing; and makes deployments safe through connection draining and slow start. Load balancing happens at several layers: internet-facing balancers such as AWS ALB or NLB, ingress controllers and internal balancers inside the platform, and client-side balancing in gRPC clients or service mesh sidecars. The choice of algorithm and health policy matters as much as having a balancer at all.

Q2BasicTrade-off

L4 vs L7?

L4 load balancing works on connections: it sees IP addresses and ports, forwards TCP or UDP flows, and picks a target once per connection. It is extremely fast, handles millions of connections, can preserve client IPs and offers static addresses, which is why AWS NLB suits extreme or non-HTTP traffic. L7 load balancing understands the application protocol: it terminates TLS, reads hosts, paths and headers, routes each request by rules, can retry, and can balance individual HTTP/2 or gRPC requests over shared connections. The cost is more processing per request. A common pattern combines both: an NLB at the edge for raw capacity, then an L7 ingress or mesh for routing.

Q3IntermediateTricky

Why is round robin risky?

Round robin assumes every target is equal and every request costs the same, and neither is true in production. If one pod sits on a noisy node or is stuck in long GC pauses, it still receives its full share of requests, which queue up behind it. At ShopNow, one pod answering in 800 ms received a fortieth of the traffic and pushed p99 to 820 ms for the whole service. Round robin also ignores mixed instance sizes and the difference between heavy and light requests. Load-aware algorithms such as least outstanding requests, power of two choices or latency-based EWMA send less traffic to slow targets automatically; with outlier ejection, p99 fell to 150 ms.

Q4IntermediateInternals

What is connection draining?

Connection draining, called deregistration delay on AWS, means the load balancer stops sending new requests to a target that is being removed but lets in-flight requests finish before the target is fully dropped. It matters during scale-in and on every rolling deploy. To work end to end, the application must cooperate: on SIGTERM it should fail its readiness check, keep serving existing requests and shut down gracefully within a timeout shorter than the drain period. In the ShopNow example, aligning a 30-second deregistration delay with Spring Boot graceful shutdown at 25 seconds and readiness set to false on SIGTERM eliminated about 300 errors with status 502 per deploy.

Q5Senior EngineerInternals

What is outlier ejection?

Outlier ejection is passive health checking: the load balancer or sidecar watches real traffic and temporarily removes a target that is misbehaving, even if its health endpoint still reports healthy. In Envoy or Istio you might eject a host after five consecutive 5xx responses, keep it out for 30 seconds and lengthen the ejection for repeat offenders. It catches problems that active checks miss, such as a pod with a broken downstream connection or a degraded node. The critical safety setting is the maximum ejection percentage, for example 20 percent, so a shared problem such as a failing database cannot make the balancer eject the entire pool and turn degradation into an outage.

Q6Senior EngineerInternals

What is power of two choices?

Power of two choices picks two targets at random and sends the request to the less loaded of the two, measured by outstanding requests or a latency estimate. It sounds trivial, but it gives load distribution close to always choosing the least-loaded target, without the cost and herd behaviour of finding the global minimum. When many independent balancers, such as sidecars, all pick the single least-loaded host from slightly stale data, they stampede it at the same moment; random sampling prevents that. Envoy's LEAST_REQUEST policy uses it by default, and combining it with EWMA latency makes it react quickly to an instance that has become slow.

Q7Technical ArchitectScenario

How handle gRPC connection pinning?

gRPC runs over long-lived HTTP/2 connections, and an L4 balancer picks a target only when a connection opens. After scale-out, existing clients keep their connections to the old pods, so new pods get almost no traffic while old ones stay hot. The fix is to balance per request, not per connection. Use an L7 proxy or service mesh that spreads individual gRPC streams across backends, or client-side balancing with xDS or a headless service so each client holds connections to many pods. Set a maximum connection age, such as five minutes with jitter, so connections are recycled, and send GOAWAY on scale-in so clients reconnect cleanly elsewhere.

Q8Technical ArchitectTricky

Why align idle timeouts?

Because if the backend closes an idle keep-alive connection before the load balancer does, the balancer may send a new request on a connection that is already closing, and the client receives a 502. It appears as a small, steady trickle of errors that is hard to reproduce. The rule is that each hop's idle timeout must be longer than that of the hop in front of it. With an ALB idle timeout of 60 seconds, the Tomcat or Netty keep-alive timeout should be longer, for example 75 seconds. The same rule applies through every proxy layer, including service meshes, NAT gateways and client connection pools.

Q9Solution ArchitectTrade-off

When use consistent hashing?

When requests benefit from always reaching the same backend for a given key, usually because that backend holds state or a warm cache for it. Routing by cartId or userId to cache nodes, sharded in-memory stores or stateful stream processors keeps hit rates high and avoids duplicate work. Consistent hashing, such as ring hash or Maglev, means adding or removing a node remaps only about one nth of the keys instead of reshuffling everything. The trade-off is balance: hot keys create hot nodes, and the algorithm ignores current load. Mitigate with virtual nodes and bounded-load consistent hashing, and keep it away from stateless tiers, where least-request balancing is better.

Q10Solution ArchitectDesign

What LB metrics matter?

Per-target metrics matter more than aggregate ones, because averages hide the single bad instance. I watch load imbalance, such as the ratio of maximum to mean requests or in-flight requests per target, alerting above about 1.5; 5xx rate and latency percentiles broken down by target and by zone; ejection counts and healthy host counts; and connection metrics such as active connections, new connection rate and rejections. At the balancer itself, track capacity units such as ALB LCUs before big events, TLS errors, and target response time against total time. Deploy-time 5xx is a key signal as well: the goal is zero errors during rolling deployments.

Newsletter

Get new tutorials every week

New ArchitectMind tutorials and interview questions, once a week. No spam, unsubscribe anytime.

Almost done! Check your inbox and click the confirmation link to complete your subscription.
Keep going in Book 10

Security, System Design & Solution Architecture

Volume I · Topic 1.1

Security Architecture

Security Architecture

Volume I · Topic 1.2

CIA Triad

Security Architecture

Volume I · Topic 1.3

Security Principles

Security Architecture

Volume II · Topic 1.1

What Is System Design?

System Design Fundamentals

Volume II · Topic 1.2

Requirements

System Design Fundamentals

Volume II · Topic 1.3

Constraints

System Design Fundamentals

Volume III · Topic 1.1

Traffic Distribution

Large-Scale & Distributed System Design

Volume III · Topic 1.3

Horizontal Scaling

Large-Scale & Distributed System Design

Volume IV · Topic 1.1

Understanding the Business

End-to-End Solution Architecture

Volume IV · Topic 1.2

Stakeholder Identification

End-to-End Solution Architecture

Volume IV · Topic 1.3

Business Capabilities

End-to-End Solution Architecture

Volume V · Topic 1.1

ADR

Architecture Decisions, Trade-offs & Risk

Volume V · Topic 1.2

Decision Context

Architecture Decisions, Trade-offs & Risk

Volume V · Topic 1.3

Alternatives

Architecture Decisions, Trade-offs & Risk

Volume VI · Topic 1.1

Legacy System Discovery

Legacy Modernization & Transformation

Volume VI · Topic 1.2

Dependency Analysis

Legacy Modernization & Transformation

Volume VI · Topic 1.3

Architecture Reverse Engineering

Legacy Modernization & Transformation

Volume VII · Topic 1.1

Architecture & Agile

Solution Architecture Delivery & Governance

Volume VII · Topic 1.2

Architecture & Product Management

Solution Architecture Delivery & Governance

Volume VII · Topic 1.3

Architecture & Development Teams

Solution Architecture Delivery & Governance

Volume VIII · Topic 1.1

Clarifying Requirements

Solution Architect Workshops, Interviews & Final Assessment

Volume VIII · Topic 1.2

Asking the Right Questions

Solution Architect Workshops, Interviews & Final Assessment

Volume VIII · Topic 1.3

Identifying Constraints

Solution Architect Workshops, Interviews & Final Assessment