Answers · The network and the web
What does a CDN actually change about my request?
In shortA CDN puts a machine near the reader that answers the request itself, so your origin often never sees it and the address it logs is not the reader's.
A CDN changes who answers. The name in the address resolves to an edge machine near the reader, and that machine terminates the TCP and TLS connection itself. It either answers from its own store or opens a separate connection to your origin. On a cache hit your origin never sees the request.
Take a reader whose edge is five milliseconds away and an origin a hundred and twenty milliseconds away. If the edge answers nine requests in ten, the average is milliseconds. If it answers half, the average is milliseconds. Raising the share from half to nine tenths cuts the average by a factor of almost four. The lever is the share, not either of the times: halving the origin time from a hundred and twenty to sixty would give milliseconds at the half share, still twice the nine-tenths figure with the slow origin. That is why the work goes into making responses cacheable rather than into shaving milliseconds off the origin.
The guess that fails
The natural guess is that the CDN is a cache sitting behind your origin. On that picture every request still reaches the origin, the cache only saves a copy, and the origin remains the server. The picture fails in two places. First, the edge is in front, not behind: the browser's TCP connection and TLS handshake end at the edge, so on a cache hit the origin's address is never contacted and nothing you built runs. Second, when the edge does fetch, the connection it opens comes from the edge or from a load balancer, not from the reader, so the address in the origin's socket is the last machine's address. The reader's address survives only in a forwarding header, which is reader-supplied text until something you control overwrites it.
The address change is not cosmetic. Every connection arriving at the application comes from the balancer or the edge, so the socket address is useless for rate limiting or for deciding which country a reader is in. The real address is carried in a forwarding header such as X-Forwarded-For, which means it is text supplied by whoever sent the request. If the edge appends to the header rather than replacing it, a reader can prepend a false address and any origin that trusts the first entry can be lied to. The header has to be overwritten at the boundary you control, and only then read. The same applies to the protocol: the origin sees HTTPS from the edge even when the reader's connection to the edge was HTTP, or the reverse, so anything that branches on the scheme has to read the forwarding header as well.
Where it stops helping
None of this helps requests that cannot be cached. Personalised responses, authenticated API calls and anything that depends on the reader's session still go to the origin, and they now travel through an extra machine. In the sixty-request example, five were uncacheable and went to the origin directly; those five determine how fast the page feels, and the edge does nothing for them except add a hop and one more place for timeouts to disagree. A cached error can also outlive the deploy that caused it: the origin returns an error for thirty seconds, the edge stores it under a default lifetime, and readers in that region see the error for an hour after the origin recovered. A timeout mismatch produces a request that the application logs as successful while the reader sees a gateway error, because the edge gave up before the application finished. And a retry at the edge, a retry at the balancer and a retry in the client library multiply into six times the load on an origin that is already slow.
Worth keeping
- A CDN is not a cache behind the origin: the edge machine is the server that terminates the reader's connection, and on a cache hit the origin never sees the request.
- The average time with an edge is \(l = h e + (1-h)o\), so the share answered at the edge matters more than either the edge time or the origin time.
- Because the origin's connection comes from the edge or balancer, the reader's address survives only in a forwarding header that must be overwritten at the boundary you control.
Where this goes next
This question is one step of From an Address to a Page, a course that works through its subject from the beginning. The page that teaches this part of it is The Machines in Between, and it reads the whole way through whether or not you have an account.
What an account changes is the practice: problems standing under every idea, marked with a reason rather than a tick, in a copy of the course that is yours.
Read that pageThe whole courseOther questions people ask about this
- Why does a DNS lookup sometimes have to ask several servers before it gets an answer?Because when no cache already holds the address, the resolver has to ask one server at a time down the hierarchy, and each reply only tells it who to ask next.
- Why does opening a connection take three messages instead of two?Three messages are needed because the server must also learn that its own reply arrived; the third message is that proof, not a formality.
- Why does a download start slow and then speed up?The sender starts with about fourteen kilobytes in flight and doubles that each round trip until something is lost, so the opening round trips measure the path rather than move data.
- Where should a session ID be stored so JavaScript can't read it?Store it in an HttpOnly cookie set by the server; that is the only browser storage JavaScript running on the page cannot read.
- What does it mean for an API method to be safe?A safe method is one that changes nothing on the server when it is called, so a caller may repeat it freely and a cache or a crawler may use it without anything being altered.
- Does signing out actually invalidate my token on the server?No. Signing out clears your browser's copy of the token, but the server keeps accepting that token until it expires.