Notes from our discussions. One idea per card, shown by topic or by course.
Open the lesson in Chrome โ start Claude in Chrome โ paste this โ bring the output to the notes thread. It keeps callouts ๐กโ ๏ธ, do's/don'ts, images, code and every comment.
You are extracting a HelloInterview course lesson from the page open in this tab. The goal is a **faithful, complete copy** of the lesson that another assistant will turn into study notes. Do **not** summarize, shorten, reword, or add anything of your own.
## Before you extract
1. Scroll the whole page from top to bottom so everything loads.
2. Do NOT use plain page-text extraction โ it flattens tables, drops link URLs and loses callout types. Read the DOM / accessibility tree, and screenshot + zoom to read images.
3. Comments: click "Show All Comments", then click every "Show more" inside long comments so the full text is visible.
4. Skip: left course sidebar and progress UI, "Get the app" banner, Listen / Focus / Quick ref buttons, "On This Page" table of contents, rating stars, "Complete & next: โฆ quiz" button, comment input box, footer.
## What to output
One Markdown document, in the **exact order the content appears on the page**:
1. **Header**
- `# <Lesson title>`
- `Course: <breadcrumb exactly as shown, e.g. "Course ยท 02 Foundations">`
- `Subtitle: <description line under the title>`
- `URL: <page URL>`
2. **Body, verbatim**
- Keep every heading level (`##`, `###`), every paragraph, list, and numbered step, word for word.
- Keep **bold**, *italic* and `inline code`. Keep links as `[text](url)` with the real URL.
- Code blocks go in fenced blocks, exactly as shown. Add a language tag only if obvious (http, json, graphql, protobuf, sql); otherwise leave it blank.
- Tables are NOT real <table> elements. Rebuild each one as a Markdown table with its header row, every row and every column, and keep the label above it (e.g. "Users table:").
3. **Callout boxes** are `div.callout.callout-tip`, `callout-warning` and `callout-info`. Use the class to pick the type and mark each one where it appears:
> [CALLOUT: TIP ๐ก] <exact text>
> [CALLOUT: WARNING โ ๏ธ] <exact text>
> [CALLOUT: INFO โน๏ธ] <exact text>
4. **Do's and Don'ts / Good vs Bad / Pros and Cons** (only if present): keep them as two clearly labelled lists:
[DO โ
] โฆ
[DON'T โ] โฆ
5. **Images and diagrams.** Images have no alt text; the caption is the short text line directly under the image (e.g. "Sharding", "Final Whiteboard"). Some diagrams are drawn as SVG text โ capture that text ONLY inside the [IMAGE] block, never as body paragraphs. Write a block at the exact spot where the image sits:
[IMAGE <n>: <caption under the image, if any>]
- Type: <diagram / screenshot / chart / sequence diagram / table image / photo>
- All text in the image, exactly: <every label, box name, arrow label, number, step number>
- Structure: <what connects to what, arrow directions, order of steps, groupings, solid vs dashed lines, meaningful colours>
- What it shows: <one or two plain sentences, nothing beyond what's drawn>
For a step-by-step diagram (e.g. a request flow), list every step in order with its label.
6. **Videos:** the lesson has a walkthrough video near the top. Write `[VIDEO: <title> ยท <length>]` where it appears. Don't transcribe it.
7. **Comments**: put them under `## Comments`, in "Popular" order. Take the top 20 comments plus all of their replies. Remove the single-letter avatar shown before names. For each one:
### <author> [ADMIN] [<badges e.g. Top 5%, Premium>] ยท <votes> votes ยท <time ago>
<exact comment text, keep its lists and formatting>
โณ reply โ <author> [ADMIN] [<badges>] ยท <votes> votes ยท <time ago>
<exact reply text>
Mark course staff or admin authors with [ADMIN].
## Rules
- Verbatim. If something can't be read, write `[unreadable]` and don't guess.
- Don't merge or drop any section, even if it looks repetitive.
- If the output is too long for one reply, split it into `PART 1/N`, `PART 2/N`โฆ at a heading boundary, and keep going until it's complete.
- At the very end, add:
## Extraction checklist
- Headings: <count> ยท Callouts: <count> ยท Images: <count> ยท Code blocks: <count> ยท Tables: <count> ยท Comments: <count incl. replies>
- Headings match the "On This Page" list? <yes / no โ list any missing>
- Comments captured: <X> of <total shown in "Comments (N)">
- Anything skipped or unreadable: <list, or "none">
๐ก Break a vague, big problem into infra pieces. There's no single right answer. You're judged on 4 things, and Problem Navigation matters most.
e.g. "Design Uber" (product) ยท "Design a rate limiter" (infra). Dashed = other guides.
What they check ยท what an interviewer writes
They spent all their time on the User table, never touching the most important part!
The multi-layer cache was an elegant solution to the massive read volume
They had strong command of Redis, Elasticsearch, and Inverted Indexes
They got quite defensive when I asked about alternative approaches
Most mid-level candidates don't fail for lack of knowledge. They fail because the clock runs out before they have a working system, and the feedback says "time management". The fix isn't going faster. It's a track to run on: 6 steps, in order. It's also your fallback when nerves hit.
Steps 1โ5 ยท make it work (functional requirements)
Everything after this is measured against your requirements, so this is where you start. Requirements come in two kinds, and you need both:
๐ฏ A. Functional requirements: what it does
โ๏ธ Write each one as "Users should be able toโฆ". For an infra system with no end users (e.g. a rate limiter), the caller is a service: "Clients should be able toโฆ".
๐ How to find them ๐ฌ: go through the actors and ask three things:
๐ฃ๏ธ Then ask the interviewer like a PM: "does it need X?", "what if Y?".
โ๏ธ Keep only the top 3. Twitter has hundreds of features. A long list hurts, and top FAANG companies grade you on choosing what matters.
Now the twist. Picture two Twitters with exactly those 3 features. One has 100 users: a single server and one database are enough. The other has 100M users who expect their feed in 200ms: now you need caches, sharding, many servers. Same features, completely different design. What made the difference is how well it must work, and that's the second kind of requirement.
โ๏ธ B. Non-functional requirements: how well it does it
โ๏ธ Write each one as "The system should beโฆ". Pick the top 3โ5, put each in context and give it a number.
๐ How to find them: walk this checklist, so you don't blank. Remember it as FCC + SLEDS ๐ฌ. For each letter, ask its question; keep the 3โ5 that really matter for this system.
| F ๐ก๏ธ Fault tolerance | A server or region dies: must it keep working? |
| C ๐ CAP | When the network splits, stay consistent or stay available? (Partition tolerance is a given.) |
| C ๐ Compliance | Any legal or industry rules on the data? (e.g. payments, personal data) |
| S ๐ Scalability | How many users and requests? Bursty (events, holidays)? Read-heavy or write-heavy? |
| L โก Latency | Which requests must be fast, and how fast? Focus on the heavy ones (e.g. Yelp search) |
| E ๐ฑ Environment | Client limits: battery, memory, bandwidth (video on 3G) |
| D ๐พ Durability | Can we ever lose data? A social feed can lose some. A bank can't. |
| S ๐ Security | Who may see or change what? How is the data protected? |
๐ฌ Tips from the comments:
Many guides tell you to do the math now. Don't, unless the answer changes a decision.
๐ค Say: "I'll skip estimates and do the math when it changes the design."
You know what to build. Now name the things it's built from. Core entities are the nouns of the system: what your API sends and your DB stores.
๐ How to find them: read your functional requirements and pick out the nouns.
Users should be able toโฆ
๐ก A Follow is a link between two users. You have to store it, so it's an entity too.
โ Also ask: who are the actors? Each one is usually an entity too (๐ค User here).
Why bother? Because the next step gets easy: each entity usually becomes an API resource, so you can map entities to endpoints almost one to one.
POST /v1/tweets ยท GET /v1/tweets/{id}
โ FollowโPOST /v1/follows
๐ฐ (no entity)โGET /v1/feed: built from Tweet + Follow
โ ๏ธ Not always 1:1: the feed isn't stored as its own entity, it's computed from others. That's fine. Use entities as the starting point, not a rule.
Keep it rough, as a quick list said out loud as a "first draft". You don't know what you don't know yet. Fields get added later, once you see what each request changes.
๐ท๏ธ Pick good names. Some interviewers check this ("one of the hardest problems in CS").
Entities are the nouns. The API is what users can do with them. It's the contract your design must satisfy, and it usually maps 1:1 to the functional requirements.
| โญ REST | Default. HTTP verbs on resources |
| GraphQL | Many clients needing different data |
| RPC (gRPC) | Internal service-to-service, when speed matters |
| WS / SSE | Real-time, added after the core API |
Don't overthink it: REST unless there's a reason not to.
POST /v1/tweets {text}
GET /v1/tweets/{id} โ Tweet
POST /v1/follows {followee_id}
GET /v1/feed โ Tweet[]
๐ฆ Resources are plural nouns: tweets, not tweet.
๐ Notice: there's no userId anywhere. The current user comes from the auth token, never from the body or path. Interviewers flag this.
Only for pipelines. If data goes through a long chain of steps (crawlers, data processing), write the steps as a list. If not, skip it.
Now draw. The trick: don't design "Twitter". Satisfy one endpoint at a time, and the design builds itself ๐
The big trap is adding complexity too early and never finishing. Keep it simple. Spot a cache or a queue? Say it, write a note, move on. It'll get its turn.
๐ฃ๏ธ Talk while you draw: how data flows, and what state changes on each request.
๐๏ธ Write the key fields next to the DB. Skip the obvious ones (name, email) and the types.
๐๏ธ Ask your recruiter which whiteboard tool you'll use (e.g. Excalidraw) and practice with it.
Step 6 ยท make it good (non-functional requirements)
Your design works, but the feed is slow: it fetches tweets from everyone you follow on every load. Good. That's exactly what deep dives are for. Go back to your non-functional list and harden.
| 100M+ DAU | โ horizontal scaling ยท caches ยท DB sharding |
| Feed < 200ms | โ fanout-on-read vs fanout-on-write + caches (the most interesting part of Twitter) |
โ ๏ธ Don't talk over the interviewer. They're looking for specific signals, and if you never pause, you miss them and lose points on communication.
Real interviews rarely wait politely for step 6. Often the interviewer jumps into a deep dive while your design is still half drawn. That's normal: the 6 steps are your default track, not a script they follow. ๐ฌ
"Sure. I'll note that the follow flow isn't drawn yet and come back to it."
"Happy to go deeper, but I may not finish the full design. Pause here, or keep going?"
๐ค Many interruptions can mean they doubt a choice. Answer with the reason, then check: "I'm using X because Y. Did you have a different concern?"
โ๏ธ The rule: they can pull you into a deep dive early. You shouldn't wander there on your own before the design works end to end. That's how candidates run out of time.
That's the loop: the first five steps get you a simple system that works. The last step makes it fast, scalable and reliable. Never the other way round, unless the interviewer pulls you there first.
Every design you draw is boxes talking over a network. Networking is a huge field ("one of the heaviest textbooks in school, gross"), but interviews need only a few layers and one story: what happens when you load a page. Learn that once and every arrow between boxes makes sense.
๐ก Know 3 layers: IP (L3) routes, TCP / UDP (L4) deliver, HTTP and friends (L7) carry your app's data. One "request" is really many packets, and each one costs latency.
Layers are abstractions. You don't need to know which voltage means 1 on the wire, only how to use the layer below. Like calling open instead of telling the disk how to read bytes.
๐ง The OSI model, top to bottom, 7 โ 1.
OSI is the textbook's 7 layers. The real internet runs on TCP/IP, which squeezes them into 4. โ not in the article
One analogy for the whole stack: sending a letter โ๏ธ. Each layer does one job, top to bottom on the sender, bottom to top on the receiver. โ Adi's notes, checked; not in the article
๐ฆ Application = OSI 7 ยท 6 ยท 5, all inside your app
๐ฉ Transport = OSI 4
๐ฅ Internet = OSI 3
โฌ Network access = OSI 2 + 1
"The important ones": 3, 4, 7.
Each layer has one job, and it does it by writing a label on the data. On the way down, every layer wraps the data in its own envelope; the receiver opens them in reverse. โ not in the article
๐ One carries about 1,500 bytes, and the TCP + IP labels take ~40 of them. A 1 MB image โ 700 packets, which is why TCP numbers them (seq #) to put them back in order.
| Says | โ๏ธ Like | |
| ๐ท๏ธ MAC | which network card, on this network. Burned in at the factory. | your name: the next hand to pass it to |
| ๐ IP | which machine, anywhere. Given by the network you join (). | the postal address on the envelope |
| ๐ช Port | which app on that machine. 0โ65535; 443 = HTTPS, 53 = DNS. | the flat number in the building |
So the IP says who it's finally for, the MAC says who gets it next, the port says which app. Now watch those packets move.
Now watch the three layers work together. DNS finds the server, TCP builds a connection over IP, HTTP asks for the page, and TCP tears it all down. Tap the diagram to step.
hellointerview.com into your browser and press enter?" used to be a popular interview question (less so in BigTech now). It's rarely part of system design, but it may save you headaches on the job.What the animation just showed you:
1๏ธโฃ ๐ง You only work at the top
๐ The app only said "GET". โก๏ธ DNS finds the IP, TCP delivers in order, IP (+ your ) routes. You never touch packets.
2๏ธโฃ โฑ๏ธ Every message costs time
๐ 1 request = 11 trips. โก๏ธ โญ Higher layer = more work per message, so an L4 load balancer beats L7 on speed (๐ Load Balancing).
3๏ธโฃ ๐งท An open connection is memory on both sides
๐ Between ACK and FIN, both sides remember it. โก๏ธ Reuse it (, ) to skip the handshake. Hold it for hours (WebSockets) = memory for hours (๐ Real-time).
IP routes to addresses. So who hands them out?
That's the base of every arrow you'll draw: DNS to find, TCP to connect, HTTP to talk. Next up: TCP isn't the only way to deliver.
Not after every request. Think of calling a shop with questions: โ analogy not in the article
๐ A 1.1 connection closes when:
Connection: close header (then both sides send a FIN),๐ Why it matters: one page = HTML + CSS + JS + images, often 50+ requests to the same server. Keep-alive reuses a few open lines instead of 50 handshakes (โ browsers keep up to ~6 per server).
๐๏ธ So why does the animation end with FIN? It shows one request on its own, start to finish. In a real browser, that FIN comes much later.
IP just throws packets at an address and hopes. Before an app can use them, someone has to decide: do we care if packets get lost or arrive out of order? That's the transport layer. In an interview it boils down to one choice: TCP or UDP.
๐ก Default to TCP: reliable and ordered, and interviewers assume it. Pick UDP only when speed beats reliability, and say what browsers get instead.
The transport layer gives us guarantees "instead of handing us a jumbled mess of packets". Three protocols live here: TCP, UDP, QUIC. โญ The real choice is TCP vs UDP. Treat QUIC as "a better TCP" that isn't widely adopted yet.
You see where a datagram came from and where it's going (IP + port). The rest is a .
The connection is a stateful "stream": two messages sent in the same stream arrive in the same order.
No setup sounds great, but losing and reordering packets "kinda suck". So UDP wins only where speed matters more than reliability, and the client can cope with a missing packet.
๐ VoIP drops the odd packet: a hiccup in the audio, but the call is still intelligible. That beats retransmitting and clogging the network with ACKs.
Interviewers expect TCP by default, often without you even saying it. That's also the course's advice. Extra points come from making a solid case for UDP "and not bungling the details".
๐ซ Choose UDP when:
| ๐ซ UDP | ๐ด TCP | |
| Connection | Connectionless | Connection-oriented |
| Reliability | Best-effort | Guaranteed |
| Ordering | None | Maintains order |
| Flow control | No | Yes |
| Congestion control | No | Yes |
| Header | 8 bytes | 20โ60 bytes |
| Speed | Faster | Slower (overhead) |
| Use cases | Streaming, gaming, VoIP | โญ Everything else |
So: choose TCP and say nothing, or choose UDP and say why, plus what browsers get. Next: what we actually send over the connection.
TCP gives us a reliable pipe. What goes through it? Almost always HTTP, with an API style on top. The interview question isn't "which is coolest?" but "what's the safe default, and when do I leave it?"
๐ก HTTP is stateless request โ response. Default to REST (resources + verbs). GraphQL when the frontend needs flexibility. gRPC for fast internal calls. REST outside, gRPC inside.
Clients send requests, servers send responses. HTTP is stateless: each request stands alone, and the server keeps nothing between them. โญ That's good. Keep the stateful part of your system as small as you can. Most simple HTTP servers are just a function of the request.
You can type this by hand: open a TCP connection with and send it.
Methods and status codes are standard, like enums. Know the common ones. Interviewers rarely dig in unless you're designing a RESTful API.
| GET | Request data. โญ , no body |
| POST | Send data |
| PUT | Update data |
| PATCH | Update a resource partially |
| DELETE | Delete data. โญ |
| โ 2xx | 200 OK ยท 201 Created (new resource) |
| โช๏ธ 3xx | 302 Found (moved temporarily) ยท 301 Moved Permanently |
| ๐ 4xx | 404 Not Found ยท 401 Unauthorized (needs authentication) ยท 403 Forbidden (understood, refuses to authorize) ยท 429 Too Many Requests |
| ๐ฅ 5xx | 500 Server Error ยท 502 Bad Gateway (invalid response from ) |
Headers are the flexible part: free-form key/value pairs. That pragmatism is a lesson in itself.
๐ท๏ธ Headers = an open slot for the future
โ๏ธ Like sticky notes on the envelope: anyone can add a new one, and a post office that doesn't understand a note just ignores it. โก๏ธ New feature = new header; old clients skip what they don't know, so nothing breaks. โ analogy not in the article
Accept-Encoding: gzip, brโ๐ฅ๏ธ Content-Encoding: brThe client says what it can handle. The server picks the most efficient one (). Old clients still work: backward compatible, degrades gracefully. ๐ The article writes "Accepts-Encoding"; the real header is Accept-Encoding.
๐ HTTPS = HTTP + TLS/SSL encryption, against and attacks. A public website uses HTTPS, without exception.
{ "userId": 42 } in the body โ DB query. An attacker edits it and reads anyone's data. Ouch!๐ค Why never trust the body? โ not in the article
โ๏ธ HTTPS is a sealed envelope: it proves nobody opened it on the way. It does not prove the letter inside is honest. The sender can be the attacker: they control their own browser, curl or Postman, and can type anything into the body, e.g. change 42 to 43.
๐ชช So who is the user? Ask the token, not the body.
Authorization: Bearer โฆโโ
server verifies it โ userId = 42โ๏ธ Like a staff badge the receptionist scans, vs someone just saying "I'm the manager". The body says what you want; the verified token says who you are.
๐ท๏ธ Why a header? It rides on every request (even GET, which has no body), stays apart from the data, and one middleware checks it before any handler runs. A header can be faked too: what makes it safe is the server's signature check, not the header itself.
๐ Then check permission: "does user 42 own order 99?" before returning it.
HTTP alone builds websites. Designs are about services talking through APIs, and there are three main paradigms: REST, GraphQL, gRPC. โญ REST is the most common.
๐ฆ Clients do simple operations on resources (think database tables, or files on a server). The challenge is modelling the resources. REST uses HTTP verbs plus path conventions, usually with JSON bodies (not required).
GET /users/{id} โ User
PUT /users/{id} โ User (update)
POST /users โ User (no id:
server assigns)
GET /users/{id}/posts โ [Post] (nested =
relationship)
updateUser and startGame are operations, not resources, so they're not RESTful.
PUT /users/{id} ยท PATCH /games with { "status": "started" }๐ Real example: Elasticsearch manages documents and indexes over REST. ๐ข REST isn't the fastest for very high throughput, and JSON is inefficient to (de)serialize. But most apps aren't bottlenecked there.
โญ Like TCP, REST is your interview default. Reach for GraphQL, gRPC, SSE or WebSockets only for needs REST can't meet. ๐ API Design lesson.
REST's weak spot shows when a frontend team (say, a mobile app) builds a new page on top of a backend API. Facebook open-sourced GraphQL around 2015 to fix exactly this.
Three options, and "none of these are particularly good":
query GetUsersWithProfilesAndGroups {
users(limit: 10) {
id username
profile { fullName avatar }
groups { name category { icon } }
status { isActive lastActiveAt }
}
_metadata { totalCount hasNextPage }
}
Trimmed from the article's query: you just list the fields and nested objects you want.
๐ค In interviews its benefits are "murky": requirements are fixed, and the interviewer wants to see you optimise specific queries, where GraphQL "is frequently just in the way". โญ Bring it up when the problem is about flexibility (adapting apps fast to changing requirements) or the requirements are deliberately uncertain.
๐ค Why "murky" in an interview? โ not in the article
GraphQL's superpower is coping with unknown future screens. An interview is the opposite: a fixed list of features, decided in the first 5 minutes. For a known screen you design the exact REST endpoint and tune its query, so GraphQL adds a layer and buys nothing. โ๏ธ Like hiring a personal shopper when you already have the shopping list.
โก๏ธ Mention it only when the prompt says many clients / many teams / screens that keep changing.
๐ฑ Why "great for mobile" and less for web? โ not in the article
๐ถ Slow, flaky network: each round trip on 4G costs far more than on office Wi-Fi, and every extra call is one more chance to fail. One query instead of 5 calls โ faster, and fewer half-loaded screens.
๐ฆ Data and battery: no over-fetching, so fewer bytes on a metered plan.
๐๏ธ Old app versions live for months: a website updates on refresh, but users skip app updates. Each app version asks for just the fields it knows, so the backend can change without breaking old apps.
โก๏ธ Web gets the same benefits, just smaller: fast network, always the latest code.
REST and GraphQL ship JSON text. When your own services call each other constantly, text gets expensive. gRPC is Google's (the "g") RPC framework: HTTP/2 + Protocol Buffers.
๐งฌ Protocol Buffers are "JSON with a more rigid schema", which makes them smaller and faster to parse:
message User {
string id = 1;
string name = 2;
}
๐ JSON { "id": "123", "name": "John Doe" }: 40 bytes, schema embedded
๐งฌ Protobuf: 15 bytes. Skinny tags, variable-length strings. "Less space and less CPU to parse!"
0A 03 31 32 33 12 08 6A 6F 68 6E 20 64 6F 65
๐ Nit: 6A is a lowercase "j", so these bytes spell "john doe", not "John Doe".
service UserService {
rpc GetUser (GetUserRequest)
returns (GetUserResponse);
}
โญ REST for public-facing APIs, gRPC for internal service-to-service, especially with binary data or when performance is critical. In many interviews, REST for both is fine. Build from there as the problem and the interviewer push.
So: HTTP carries it, REST shapes it, GraphQL and gRPC are for specific needs. All of them are the client asking. Next: when the server has to speak first.
| GET | Safe + idempotent. No body, so parameters go in the URL: GET /config?config_id=123 |
| POST | Not idempotent |
| PUT | Replaces the whole resource. |
| PATCH | Partial update. Not guaranteed idempotent |
| DELETE |
updateUser) are RPC-style, not REST.users { posts { comments } } for 20 users can become 1 + 20 + ~100 backend calls. You need batching, caching, custom resolvers and query limits. GraphQL moves backend work, it doesn't remove it.userService.getUser("123")..proto file, then generate client and server code in many languages.Everything so far is the client asking. But an auction, a chat or a video call needs the server, or another user, to speak first. gRPC can stream, but no browser supports it today. So the web has three tools, one for each shape of conversation.
๐ก Server โ client only: SSE. Both ways, high-frequency: WebSockets (justify them!). Audio/video calls: WebRTC, peer-to-peer over UDP.
Server-Sent Events is "a nice hack on top of HTTP": a spec that lets the server stream many messages, over time, in a single response.
{ "events": [
{ "id": 1, โฆ },
โฆ
{ "id": 100, โฆ } ] }Wait for the whole blob, then process it.data: {"id": 1, โฆ}
data: {"id": 2, โฆ}
โฆ
data: {"id": 100, โฆ}Each line is its own message, handled on arrival.โ ๏ธ "Tradeoffs!" Some nasty, misbehaving networks batch all the SSE chunks into one response, which brings back exactly what we were avoiding.
๐ฏ Use it when clients should get notifications or events as soon as they happen, e.g. keeping auction bidders up to date on the current price. ๐ Realtime Updates covers the server side.
SSE pushes one way only. For real-time bidirectional traffic, WebSockets give a persistent, TCP-style connection with broad support, browsers included. The server pushes without a request, and so does the client.
๐ฏ Use them for high-frequency, persistent, bi-directional communication: real-time apps, games, anything that must send and receive the moment it happens. Just request/response, or SSE pushes are enough? Then WebSockets are overkill.
The third shape: two users talking to each other, not to you. WebRTC connects browsers peer-to-peer. It's built for video and audio calls, and it's the only app protocol here that uses UDP.
๐ง Peer-to-peer is harder: most clients don't allow inbound connections, and most users sit behind a NAT (network address translation) device. Two standard workarounds:
๐ฏ โญ Use it for audio/video calling and conferencing. Collaborative editors? Occasionally, especially at scale. But most don't need thousands of clients and need a central server anyway, which is why the course's Google Docs design uses WebSockets. The alternative is WebRTC + , sending updates straight between clients.
So: SSE when only the server talks, WebSockets when both do, WebRTC when the users talk to each other. Each one holds connections open. Next: spreading all those connections across many servers.
:ping comment every 15โ20 s) and SSE stays open for hours behind ALB or nginx; reconnects are only for real drops (deploys, network changes).| REST / HTTP | Request-response ยท client โ server ยท stateless ยท web pages, APIs |
| GraphQL | Request-response ยท client โ server ยท stateless ยท flexible queries |
| gRPC | RPC + streaming ยท both ways ยท HTTP/2 ยท microservices |
| SSE | Server push ยท server โ client ยท persistent ยท live updates |
| WebSocket | Full-duplex ยท both ways ยท persistent ยท chat, live data |
| WebRTC | Peer-to-peer ยท direct ยท persistent ยท calls, file sharing |
We know how one client talks to one server. But one server won't hold, so we scale. The moment there are three servers, every client has the same question: which one do I talk to?
๐ฝ๏ธ Think of a busy restaurant. One chef can't cook for the whole street, so you hire more chefs. Now every diner walking in asks: which chef cooks for me? This whole card is that question. โ analogy not in the article
๐ก Horizontal scaling needs load balancing. Internal services: client-side (built into gRPC). Everything else: a dedicated LB. โญ L4 for WebSockets, L7 for HTTP.
๐งโ๐ซ The author scales vertically wherever possible: modern hardware is incredibly powerful, and the days of thousands of tiny servers are over (๐ Numbers to Know). โญ But in interviews, horizontal scaling is the most common pattern.
๐ฝ๏ธ Vertical = give your one chef a bigger stove. Horizontal = hire more chefs. A bigger stove has a ceiling, and if that chef gets sick, nobody eats. โ analogy not in the article
Adding boxes to the whiteboard doesn't help if clients don't know which one to call.
Spread the load by deciding which server handles each request. Two ways: decide on the client side, or on the server side with a dedicated load balancer.
The client asks a service registry (directory) for the list of servers, then calls one directly. It polls, or gets pushed updates when servers are added or removed.
๐ฝ๏ธ Diners look at a board of free chefs by the door (the registry) and walk straight to one. No one stands in the way, so it's fast. But if the board is old, a diner may walk to a chef who just went home. โ analogy not in the article
โก Very fast: no extra network hop on every request, just a periodic sync of the server list. Two examples:
๐ DNS is client-side load balancing too. Each lookup of example.com returns a rotated list of IPs (a different order, or even a different set), so different clients hit different servers.
๐ DNS is a phone book that lists the restaurant's numbers in a different order for each caller, so calls spread out. The catch: people keep the old page for a while (the TTL). โ analogy not in the article
So when does client-side work? It depends on how many clients must hear about changes, and how fast.
โณ Why "delays": update time grows with the number of clients to notify. DNS entries have a TTL (time to live), so far-flung DNS servers can cache them for their own clients, but your updates can never be faster than the TTL.
๐ค Great for internal microservices (built into gRPC). Interviewers rarely ask about the lines between your services, but if they do, mention client-side load balancing!
For everything else: clients you don't control, clients that must see changes quickly, or clients that shouldn't even know there are many servers. Put a server or hardware device in the middle.
๐ฝ๏ธ A host at the door. Every diner stops there first (the extra hop), and the host seats them. Diners never see the kitchen, and the host knows right away when a chef leaves or joins. โ analogy not in the article
"Load balancer decides which server to route to."
๐งฑ LBs work at different layers of the stack. Which one depends on what your app needs.
โ๏ธ L4 is a phone switchboard: it connects your call to one line and steps away. It never listens to what you say, so it can't route on it, but it's fast. A WebSocket is a long phone call: connect once, then talk for hours. That's exactly what a switchboard is for. โ analogy not in the article
๐จ L7 is a receptionist who opens every letter: "billing? โ desk 3, support? โ desk 5". Smart routing by what's inside, but reading costs time (CPU). For a long phone call there's nothing to read, so the receptionist just holds two lines open for hours. โ analogy not in the article
| 4๏ธโฃ L4 | 7๏ธโฃ L7 | |
| Looks at | IP + port | URL, headers, cookies |
| Connection | As if client โ server direct | Ends at the LB, new one to server |
| Cost | Fast, minimal inspection | More CPU |
| Pick for | โญ WebSockets, raw speed | โญ HTTP, e.g. long polling |
| AWS | NLB | ALB |
โ๏ธ So: switchboard or receptionist? โ not in the article
๐ Ask: does the LB need to read the request to decide? โก๏ธ No (WebSockets, raw speed) โ L4. Yes (route by path, header, cookie) โ L7.
Balancing is half the job. The LB also watches its servers, and that automatic failover is what makes LBs essential for high availability, with no human needed.
๐ฝ๏ธ The host peeks into each kitchen every few seconds. TCP check = "is the kitchen door open?" L7 check = "can you actually cook a dish?" Chef down โ stop seating diners there until they're back. โ analogy not in the article
A dedicated LB also lets you choose how traffic is spread.
| ๐ Round Robin | Sequentially across servers. โญ Default |
| ๐ฒ Random | Randomly across servers. โญ Default |
| ๐ Least Connections | Server with the fewest active connections. โญ For SSE / WebSockets |
| โฑ๏ธ Least Response Time | Server with the fastest response time |
| #๏ธโฃ IP Hash | Client IP picks the server (session persistence) |
๐ Round robin = dealing cards: one each, in turn. Least connections = joining the shortest checkout queue at the supermarket. IP hash = your regular waiter: same face every visit. โ analogy not in the article
๐ Enterprise hardware LBs handle 100s of millions of requests per second; software ones less. Scaling the LB itself is almost never asked in SWE interviews (except networking specialisations). If your LB throughput looks huge, mentioning hardware LBs "is a good way out".
So: client-side for services you control, a dedicated LB for everyone else; L4 to keep connections, L7 to read requests. With servers spread out, the next problems come from geography and failure.
โ๏ธ Not "because it's TCP": HTTP runs on TCP too, and HTTP goes to L7. The reason: a WebSocket is one long phone call, not many letters. The switchboard (L4) connects it once and steps away. A receptionist (L7) would have nothing to read, yet hold two lines open for hours. โ analogy not in the article
Protocols โ, load balancing โ, persistent connections โ, high availability โ. Two deep-dive favourites are left, and both come from the real world: physics makes distance slow, and networks break.
๐ก Two real-world problems, and the tools for each. Every tool is explained further down ๐
๐ 1. Distance is slow โ plain words + analogies, not in the article
Data needs time to travel. Fix: keep it near the user (that's data locality).
๐ฆ CDN: a corner shop with copies of popular items, so you don't drive to the far warehouse.
๐บ๏ธ Regional partitioning: each region gets its own branch with its own records.
๐ฅ 2. Networks fail
โฑ๏ธ Timeout + retry with backoff: no answer? Call back later, waiting longer each time. Jitter: not everyone calls back on the same second.
๐ Idempotency key: an order number, so a repeated order isn't made twice.
๐ Circuit breaker: the fuse in your house. It trips so one fault doesn't spread, then tests again later.
Global services put servers around the world: several data centers in one region (Amazon's "availability zones", so a broken pipe in one building doesn't take you down), repeated in cities across the globe. "A great victory for humanity", but now distance costs time.
That's the theoretical minimum, before any processing. This is why geographic distribution is essential for low latency.
The fix, everywhere in computing: data locality. Performance is best when the data sits as close as possible to the computation.
๐ Data locality = keep the books you need on your desk, not in a library across town. Every trip to the library costs time, however fast you read. โ analogy not in the article
๐ช A corner shop stocks copies of the popular items from the big warehouse. Milk and bread: grab it up the road. Something rare or fresh off the line: still the long drive. โ analogy not in the article
Uber's key insight: a rider in Miami never wants a driver who's in New York. Millions of riders and drivers a day, but only a few thousand in any one city. So the architecture can mirror that.
Each region has its own database in that geography, with request servers co-located next to it. Booking a ride or checking status stays inside the region. "Nice and optimal!"
๐ฆ Like a bank with city branches: your account lives at your branch, so everyday visits never call head office in another country. โ analogy not in the article
The other frequent deep dive. Servers crash, solar flares flip bits, power gets cut. The network fails too: cables get cut, routers fail, packets get dropped.
The most elementary hygiene: expect a call to take X, set a timeout, give up and try again. A temporarily slow server will likely answer the retry. But retries are double-edged: retrying requests that keep failing makes things worse.
โณ Backoff: don't retry immediately. Wait a little, and longer after each failure, so the system can recover. ๐ฒ Jitter: add randomness, so clients don't all retry at the same moment "like a jackhammer".
๐ Calling a busy friend: no answer โ wait 1 min, then 2, then 4 (backoff). If 1,000 people all redial on the exact same second, the line jams again; each waiting a slightly random time (jitter) spreads the calls out. โ analogy not in the article
๐ค โญ Interviewers often listen for the magic phrase "retry with exponential backoff". In more senior interviews, be ready to explain jitter. ๐ AWS: timeouts, retries and backoff with jitter.
Retries are cool, except when they have side effects. โญ This is why idempotent APIs are the key to safe retries: calling them many times gives the same result. GET is the classic one: the content may change, but fetching it doesn't change the system. For writes, add a key ๐
Senior candidates often get "what happens when this service goes down?" Sometimes "fail and retry until it's back" is fine. But picture a database that went down cold and has to boot one instance at a time. A firehose of retries and angry users can pin each instance before it starts: a thundering herd. You can't get the first one up, so the whole DB never comes back. Stuck!
๐๏ธ Thundering herd = a Black Friday crowd at the doors: open one door and the crush knocks the first clerk over, so the shop never manages to open. โ analogy not in the article
What does a cascade look like in real life? Usually it starts with something slow, not something dead. ๐ โ example not in the article
๐ A traffic jam: one lane is blocked, cars back up into the junction, and soon streets that never used that lane are stuck too. โ analogy not in the article
The first tool that stops it is the circuit breaker:
Inspired by electrical circuit breakers: it stops cascading failures and gives failing services time to recover.
๐ The fuse in your house: a fault trips it, and power to that circuit stops at once (fail fast) instead of burning the wiring. After a while you try flipping it back (a few test requests); if it holds, power is back. โ analogy not in the article
๐ค Bring them up when the interviewer digs into reliability, failure modes or disaster recovery. That knowledge is usually "won at 3:00am battling a hardware failure when the system Just. Won't. Come. Back. Up." Put them on:
A breaker alone isn't the whole answer. Each tool fixes one step of the cascade above. โ bulkhead, shedding, queue: not in the article
๐ค When they ask "what if Payment goes down?" โ not in the article
1๏ธโฃ Blast radius: "Who calls Payment? Only checkout should break, not browse or login."
2๏ธโฃ Don't wait: "Timeouts on every call, retries with exponential backoff and jitter, and an idempotency key so a retry can't double-charge."
3๏ธโฃ Don't hammer: "A circuit breaker on the Payment call, with a fallback: accept the order and confirm payment later."
4๏ธโฃ Contain it: "A bulkhead (separate pool) for Payment calls, so the rest of the site keeps its threads."
5๏ธโฃ Decouple: "If payment can be async, put it on a queue and charge when the bank recovers."
๐ Saying them in the order the cascade happens shows you've seen one, which is exactly what this question is screening for.
Networking choices touch latency, throughput, reliability and security. The course gives sensible defaults, but most problems have no single right answer: justify each choice from the requirements, and show the interviewer how you weigh the trade-offs.
๐งช Try it yourself: capture your own traffic in Wireshark to see the whole stack in action. Then fake a nasty cell connection (latency, packet loss) with Mac's Network Link Conditioner (via Xcode) and watch apps break.