Building Blocks · Load Balancing and API Gateways

Load Balancers, Gateways and Rate Limits

How traffic reaches healthy servers: balancing algorithms, health checks, L4 versus L7, sticky sessions, API gateways and edge rate limiting.

  • 8 min read
  • 11 practice questions
On this page
  1. Description
  2. What a load balancer does
  3. Choosing a server
  4. L4 versus L7
  5. Stateless servers, and why sticky sessions hurt
  6. The balancer is a single point of failure
  7. API gateways
  8. Rate limiting
  9. Which tool at which layer?
  10. Check yourself
  11. Key takeaways
  12. Quick revise
  13. Practice

Description

One server is easy: clients know its address, and every request goes there. The moment you need two - because traffic doubled, or because one server dying shouldn't take the service down - you need something in front of them that knows which servers are healthy right now and spreads requests among them. That's a load balancer. In front of a public API it usually grows into an API gateway, which also checks who's calling and how often.

Why not just list both servers' addresses in DNS? Because DNS answers are cached for minutes by clients and resolvers: when one server crashes, a slice of users keeps being sent to the dead machine, and nothing retries them elsewhere. In this lesson:

  1. What a load balancer does - one address, spreading load, health checks, draining.
  2. How it picks a server.
  3. Layer 4 versus layer 7 balancing.
  4. Stateless servers, and why sticky sessions hurt.
  5. API gateways and rate limiting with a token bucket.

What a load balancer does

  1. One stable address. Clients call api.example.com; the balancer owns it.
  2. Spreading load over a pool of backend servers.
  3. Health checks. Every few seconds it probes each server (GET /health); after a few failures the server is taken out of rotation, and put back when it recovers.
  4. Connection draining. When a server is being removed - a deploy, a scale-in - the balancer stops sending it new requests but lets in-flight ones finish.

Choosing a server

AlgorithmHowGood for
Round robinEach server in turnRequests of similar cost
Weighted round robinIn turn, bigger servers more oftenMixed server sizes
Least connectionsThe server with the fewest open requestsRequests of very different cost (a 10 ms read next to a 5 s report)
Hashing (by client or key)The same key always to the same serverCaches local to a server; rarely needed with stateless servers

Round robin can pile slow requests onto one server while others idle; least-connections adapts to it.

L4 versus L7

  • Layer 4 (transport) balancers forward TCP (or UDP) connections by address and port. They're fast and protocol-agnostic, but can't see the HTTP request - no routing by path, no retries of individual requests. Once a long-lived connection is placed, every request on it goes to the same server.
  • Layer 7 (application) balancers terminate the connection, read the HTTP request and can route /api/* and /images/* to different pools, terminate TLS, add headers, retry a failed request on another server and balance individual requests over long-lived HTTP/2 connections.

Most web APIs sit behind an L7 balancer; L4 shows up for raw TCP protocols or as the very first tier in front of L7 balancers. A typical public API stacks them:

/orders/*

/users/*

/images/*

Clients

DNS
api.example.com

L4 balancers
(redundant pair or cloud NLB)

API gateway / L7 balancers
TLS, auth, routing, rate limits

Order service pool

User service pool

Image service pool

/orders/*

/users/*

/images/*

Clients

DNS
api.example.com

L4 balancers
(redundant pair or cloud NLB)

API gateway / L7 balancers
TLS, auth, routing, rate limits

Order service pool

User service pool

Image service pool

Stateless servers, and why sticky sessions hurt

If a user's session lives in one server's memory, every request must go back to that server - "sticky sessions", usually by a cookie the balancer reads. It works until that server dies (the users on it are logged out) or you scale in (same). It also unbalances load, because heavy users stay where they are. The fix is to keep servers stateless: sessions in a shared store (Redis) or in a signed token the client carries, so any server can handle any request and the balancer is free to route.

The balancer is a single point of failure

A single load balancer in front of twenty servers means one machine can take the whole service down. Production setups run balancers as an active-passive or active-active pair sharing a virtual IP, or use a managed cloud balancer that's redundant across zones. On a design diagram, give the balancer 2+ instances or say it's a managed, multi-zone service.

API gateways

An API gateway is an L7 entry point with API concerns built in:

  • Authentication - validating tokens once at the edge.
  • Routing - /orders/* to the order service, /users/* to the user service.
  • Rate limiting and quotas - per API key or user.
  • Request shaping - timeouts, retries, response caching, request size limits.

Load balancers still sit behind it (or it balances itself) for each service's pool.

Rate limiting

Without limits, one buggy client in a retry loop - or a scraper - can take the capacity everyone else needs. Limit per client identity (API key, user, or IP for anonymous traffic) at the gateway, before the request costs anything.

A token bucket with capacity 20, refilled at 5 tokens per second. An idle client's burst of 30 gets 20 through and 10 rejected; after that it can sustain 5 requests a second.

The token bucket is the usual algorithm: a bucket holds up to B tokens and refills at r per second; each request takes a token, and a request that finds the bucket empty is rejected. It allows a burst of B requests at once while holding the long-run rate to r. (A fixed window - "100 per calendar minute" - is simpler but lets a client send 200 in two seconds across a window boundary.)

Rejected requests get 429 Too Many Requests with a Retry-After header, so well-behaved clients back off instead of hammering. With several gateway nodes, either keep the counters in a shared store such as Redis (an atomic increment per request), or give each node a fraction of the limit and accept some slack.

Which tool at which layer?

NeedWhere it belongs
One address, health checks, spreading loadLoad balancer (L4 or L7)
Routing by path or header, TLS termination, per-request retriesL7 balancer or gateway
Authentication, API keys, quotas, rate limitsAPI gateway
Spreading load across regionsDNS-based or anycast global load balancing (deep dive)
Service-to-service calls inside the platformClient-side balancing or a service mesh (deep dive)

Going further. The deep dive (next tab) covers how balancers pick servers well at scale (the power of two random choices), retry storms and retry budgets, health checks that take down healthy fleets, why long-lived connections defeat L4 balancing, global load balancing, and rate limiting across many gateway nodes.

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Half your requests take 5 ms and a few take 3 seconds. Round robin or least-connections?

Show answer

Least-connections. Round robin keeps handing new requests to a server that's stuck on several 3-second ones; least-connections sends them to whichever server has the fewest in flight.

2. Why does DNS round robin alone make a poor load balancer?

Show answer

It has no health checks, and DNS answers are cached by clients and resolvers - so a dead server keeps receiving traffic until caches expire, with nothing to retry the request on a healthy server.

3. A token bucket has a capacity of 20 and refills at 5 per second. A client has been idle for a minute and sends 30 requests at once. What happens?

Show answer

The bucket is full (20 tokens), so the first 20 go through immediately and the other 10 get 429s. After that the client can sustain 5 requests per second.

Key takeaways

  • A load balancer is one address, spread load, health checks and connection draining.
  • Round robin for uniform requests; least-connections when request costs vary.
  • L4 forwards connections; L7 reads HTTP - path routing, TLS termination, per-request retries.
  • Keep servers stateless; sticky sessions tie users to a server that can die.
  • Run the balancer redundantly - one balancer is a single point of failure.
  • Rate-limit per client at the gateway with a token bucket; answer 429 with Retry-After.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before a design interview, and open the full lesson for anything that doesn't ring a bell.

What goes where

NeedWhere it belongs
One address, health checks, spreading load, drainingLoad balancer (L4 or L7)
Routing by path or header, TLS termination, per-request retriesL7 balancer or gateway
Authentication, API keys, quotas, rate limitsAPI gateway
Spreading load across regionsAnycast or DNS-based global load balancing
Service-to-service callsClient-side balancing or a service mesh (Envoy sidecars)

Pick the algorithm

AlgorithmGood for
Round robinRequests of similar cost
Weighted round robinMixed server sizes
Least connectionsRequests of very different cost (5 ms next to 3 s)
Hashing by keyServer-local caches; rarely needed with stateless servers
Power of two random choicesLarge fleets with many balancers

L4 vs L7

  • L4 forwards TCP/UDP connections: fast, protocol-agnostic, blind to HTTP. A long-lived connection stays on one server.
  • L7 terminates the connection and reads HTTP: path routing, TLS termination, per-request retries, balancing each request over HTTP/2.

Rate limiting

  • Token bucket: capacity B, refill r/s - bursts of B, long-run rate r. Capacity 20, 5/s: an idle client's burst of 30 → 20 accepted, 10 rejected, then 5/s.
  • Answer 429 Too Many Requests with Retry-After.
  • Limit per API key or user (IP for anonymous), at the gateway, before the request costs anything.

The traps

  • DNS round robin as a balancer - no health checks, cached answers keep sending users to dead servers.
  • Round robin with uneven requests piles slow work on one server.
  • Sticky sessions - users lose sessions when their server dies; load stays unbalanced. Keep servers stateless (sessions in Redis or a signed token).
  • One balancer is a single point of failure - run a redundant pair or a managed multi-zone balancer.
  • Fixed-window limits allow 2× at a window boundary.

Staff-level points, one line each

  • Power of two choices: placing 10,000 requests on 10,000 servers, the busiest got 6 at random vs 3 with best-of-two - exponentially better with almost no information, and no herding across balancers.
  • Retry storms: 3 layers × 4 attempts = 64 calls to the failing service per user request (3 × 3 attempts = 27). Retry at one layer, use retry budgets (~10% of traffic), exponential backoff with jitter, circuit breakers, and only retry idempotent calls (or with idempotency keys).
  • Load shedding: reject excess early with a cheap 503 + Retry-After; shed low-priority traffic first.
  • Health checks: separate liveness from readiness; keep shared dependencies (the database) out of them, or one blip removes the whole fleet. Fail open below a healthy threshold (Envoy's panic threshold, 50% by default). Require several failures to remove, several successes to restore; slow-start new servers.
  • Long-lived connections (HTTP/2, gRPC, WebSockets) behind L4: new servers get no traffic. Balance at L7, cap connection age (GOAWAY), or use client-side balancing.
  • Across regions: anycast fails over in seconds; DNS in minutes (TTLs, resolvers ignoring them, resolver ≠ user location). The data layer is usually the hard part of region failover.
  • Distributed limits: a shared Redis counter is exact but adds a round trip and a dependency (atomic INCR/Lua; usually fail open if Redis is down); local 1/N limits have slack - fine for abuse, not billing; sliding windows remove most of the boundary burst.

Say it in an interview

  • "Least-connections, because report requests take seconds while reads take milliseconds."
  • "Retries only at the gateway, with a budget and jitter - inner services fail fast."
  • "Readiness checks stay local, so a database blip doesn't remove the whole fleet."
  • "Rate limits are a token bucket in Redis per API key; if Redis is down we fail open."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Load Balancers, Gateways and Rate Limits free

Practice Load Balancers, Gateways and Rate Limits free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime