We use analytics cookies.We use cookies to analyze site traffic and improve your experience.
Loading...
System Design Masterclass · Load Balancing Proxies
Free preview: the first 2 parts of this 10-part lesson.
Already bought the course? Sign in to read the whole lesson.
this lesson is part of
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design courseread the rest of this lesson in
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design coursein Load Balancing Proxies
This lesson is part of the full System Design Masterclass. Unlock it along with 769 other lessons for a one-time payment.
One-time payment by card or PayPal
Get Lifetime AccessOne-time payment: UPI, card or netbanking
Get Lifetime Access18 Foundation lessons are free, no payment needed. Try them now
It is easy and good
“It is really nice and good Please join the course”
The last two lessons routed on the client. A cookie names a browser. An address names a network path. Both were ways of getting a request back to a machine that happened to be holding something.
This lesson routes on something else entirely: a key that names whose data the request is about. A tenant. A document. A device. A model. Something that has a home of its own, independent of who is asking for it.

The first two rows are the previous two lessons. The last three are this one, and the difference is that what they name genuinely lives somewhere.
Here is the concrete version. A multi-tenant product has three database shards. Each customer's rows live on exactly one of them. If a request for Acme lands on a server wired to the wrong shard, that server has to cross the network to fetch data another server had ready, so the request is slower for no reason at all.
Route on the tenant, and every Acme request reaches a server already connected to Acme's shard, with Acme's data in its local cache and Acme's connection pool already open.
That is the entire idea. Everything after this is about the ways it goes wrong.

Each tenant lands on its own backend and stays there. Then a request arrives with no header, a client claims to be a tenant it is not, and one backend leaving moves every tenant.
Every one of those three surprises is a section of this lesson. None of them is visible in the usual explanation, which is a code comment showing hash(tenant) % 3 and a sentence about data locality.
The has to get the key out of the request before it can choose anything. There are four normal places it can live, and they are not equally safe.

A subdomain, a path prefix, a verified token claim and a client-set header are four different levels of trust. The edge turns whichever one it uses into a single header the backends can rely on.
The step people skip is the delete. It is very common to write the rule as "set the tenant header if it is not already present", because that reads as defensive and it is the opposite. A client that sets the header first now controls its own routing, and every backend downstream sees a header that looks like it came from the proxy.
Overwrite unconditionally. No request should ever reach a backend carrying a tenant id the edge did not put there itself.
Beyond where it lives, a key has to have a few properties to be usable at all.

Available early, cheap to read, stable, coarse, and never trusted for anything except routing.
The fourth one is worth a moment because it is easy to get backwards. A key with very high cardinality, such as a request id or a timestamp, spreads perfectly evenly across your servers. It also gives every request a different destination, which is random routing with a hash function in front of it. Grouping only means something when many requests share a key.
The fifth property is the one that becomes an incident, and it has its own section later.