The parts of networking that actually show up in system design interviews — protocols, load balancing, and the failure modes that bite you at 3 a.m.
At its core, networking is about connecting devices and letting them communicate. Systems are nearly always built from independent devices talking over a network.
Networks use a layered architecture (the OSI model) that greatly simplifies life for application
developers sitting on top. Each layer is an abstraction: when you request a webpage you don't care which
voltages represent a 1 or a 0 on the wire — you just use the next layer down. It's like calling open() instead of instructing the disk how to read bytes.
The full stack is fascinating, but three layers come up most in interviews. Hover a layer to lift it.
Application protocols that abstract data for web apps. Built on TCP (or UDP, for WebRTC). Processed in User Space — flexible, easy to modify.
End-to-end communication services — reliability, ordering, flow control — layered on top of the network layer. Processed in Kernel Space (hard to change, very efficient).
IP handles routing and addressing — breaking data into packets, forwarding between networks, and best-effort delivery to any destination IP.
These layers work together to enable every network communication. The higher up the stack you go, the more latency and processing is required — a fact that matters directly for the load-balancer discussion later.
Type a URL and several layers spring into action. Here's a plain HTTP-over-TCP page load, start to finish.
Resolve the domain (e.g. hellointerview.com) to an IP like 32.42.52.62.
SYN → client requests connection · SYN-ACK → server acknowledges · ACK → client confirms, connection established.
Client sends an HTTP GET for the page.
Server builds the response. (Usually the only latency most engineers think about and control.)
Server returns the page content.
FIN → ACK → FIN → ACK. Both sides close their half of the connection.
Application code can take reliability and ordering for granted — TCP delivers data correctly, in order, and tells the app if it can't.
One conceptual "request" hides many packets and round trips. Each adds latency you ignore until you can't.
The connection is shared state. Without keep-alive or HTTP/2 multiplexing, you repeat setup for every request — real overhead for persistent-connection systems.
The network layer is dominated by IP. Nodes get IPs (usually from a DHCP server) at boot. These addresses are arbitrary — they only mean something because we advertise them.
You can build a private network with any IPs you like, but for internet traffic to find your servers you need public IPs that are routable and allocated by a RIR. Internet routing infrastructure is optimized to find public IPs.
17 (e.g. 17.0.0.0) belongs to Apple — the internet backbone knows to route those packets
straight to their routers.The transport layer gives you guarantees instead of a jumbled pile of packets. The three protocols are TCP, UDP, and QUIC — but the real interview choice is TCP vs. UDP. Treat QUIC as "a better TCP" without the broad adoption baseline.
The machine-gun of protocols — "spray and pray." Connectionless, minimal features over IP, very fast. You see source/destination IP+port; everything else is a binary blob.
Perfect when speed beats reliability: live video, gaming, VoIP, DNS lookups. A dropped VoIP packet is just a hiccup — far better than clogging the network with retransmits and ACKs.
The workhorse of the internet. Reliable, ordered, error-checked delivery over a three-way-handshake connection — a stateful stream. Unacknowledged messages get retransmitted.
Ideal where data integrity matters — i.e. basically everything UDP isn't a good fit for.
Interviewers assume TCP by default — it often doesn't even need mentioning. You earn points by making the case for UDP and getting the details right. Reach for UDP when:
| Feature | UDP | TCP |
|---|---|---|
| Connection | Connectionless | Connection-oriented |
| Reliability | Best-effort | Guaranteed |
| Ordering | No guarantee | Maintains order |
| Flow Control | No | Yes |
| Congestion Control | No | Yes |
| Header Size | 8 bytes | 20–60 bytes |
| Speed | Faster | Slower (overhead) |
| Use Cases | Streaming, gaming, VoIP | Everything else |
HTTP is the de-facto standard for web data: a request-response protocol. It's stateless — each request is independent, the server holds nothing about prior requests. That's good: minimize stateful surface area. Most simple HTTP servers are just a function of the request params.
Headers are flexible key/value pairs — a great lesson in interface design for unknown future use-cases.
Content negotiation is the classic case: a client sends Accept-Encoding: gzip, br, the server replies with Content-Encoding: br if available — backward compatibility plus graceful
degradation.
The most common paradigm in interviews. The core idea: clients perform operations against resources (think database tables or files). REST leans on HTTP verbs plus conventions for paths and bodies, usually with JSON. Your Core Entities often map directly to resources.
# Read a user GET /users/{id} -> User # Update an existing user PUT /users/{id} -> User { "username": "john.doe", "email": "john.doe@example.com" } # Create (server assigns the id) POST /users -> User { "username": "stefan.mai", "email": "stefan@hellointerview.com" } # Nested resources for relationships GET /users/{id}/posts -> [Post]
updateUser becomes PUT /users/{id}; startGame becomes PATCH /games with {"status":"started"}. REST is the
default for interviews — reach for alternatives only when REST can't meet a specific need. JSON
is inefficient to (de)serialize, but most apps aren't bottlenecked there.Open-sourced by Facebook (~2015). It lets the frontend request exactly the data it needs, solving two problems with REST:
Page needs many requests / round trips — extra overhead and latency on load.
Responses pack far more than needed to guard against future cases — slow and bloated.
query GetUsersWithProfilesAndGroups($limit: Int = 10, $offset: Int = 0) {
users(limit: $limit, offset: $offset) {
id
username
profile { id fullName avatar }
groups { id name description category { id name icon } }
status { isActive lastActiveAt }
}
_metadata { totalCount hasNextPage }
}
The query names the fields and nested objects; the backend responds in exactly that shape. Sweet spot: complex clients and multiple teams making wide queries over overlapping data — where the frontend needs to iterate fast.
A high-performance RPC framework from Google using HTTP/2 and Protocol Buffers — like JSON but with a rigid schema for better performance and serialization.
message User {
string id = 1;
string name = 2;
}
service UserService {
rpc GetUser (GetUserRequest) returns (GetUserResponse);
}
A chunky JSON object (~40 bytes) becomes a skinny binary encoding (~15 bytes) — less space, less CPU to parse:
{ "id": "123", "name": "John Doe" } // ~40 bytes JSON
0A 03 31 32 33 12 08 6A 6F 68 6E ... // ~15 bytes protobuf
Definitions compile into client + server stubs across many languages. gRPC ships streaming, deadlines, client-side load balancing, and more — built for microservices at scale. Some benchmarks show ~10× throughput over JSON-over-HTTP.
A spec on top of HTTP that lets a server stream many messages over a single HTTP response. Normal HTTP gives one cohesive JSON blob you process once fully received — useless for push. SSE sends chunks:
data: {"id": 1, "timestamp": "2025-01-01T00:00:00Z", "description": "Event 1"}
data: {"id": 2, "timestamp": "2025-01-01T00:00:01Z", "description": "Event 2"}
data: {"id": 100, ...}
Each line is a separate message the client processes as it arrives (one TCP connection, many small packets).
EventSource object auto-reconnects with
the ID of the last message received, and servers are expected to resend anything missed. Some
misbehaving networks batch all SSE responses into one — recreating the exact problem you were avoiding.
Most interviewers don't know these; people who've actually shipped SSE do.Where to use: notifications/events as soon as they happen — e.g. keeping bidders updated on an auction's current price.
A persistent, TCP-style connection enabling real-time, bidirectional communication with broad support (browsers included). Both sides push without waiting for a request. Initiated via an HTTP "upgrade" so you can reuse existing session info (cookies, headers).
WebSockets don't dictate an application protocol — you have a binary channel and define your own messages (serialized JSON is a great option).
The most unusual protocol — direct peer-to-peer communication between browsers, no intermediary server for the data exchange. The only app-level protocol here that uses UDP. Great for video/audio calling and conferencing.
P2P is harder than client-server because most clients block inbound connections and sit behind a NAT. WebRTC works around this:
Session Traversal Utilities for NAT. Techniques like "hole punching" that let peers discover publicly routable addresses/ports, shared via the signaling server.
Traversal Using Relays around NAT. A relay service that bounces traffic through a central server when a direct connection fails.
To scale you go vertical (bigger servers) or horizontal (more servers). Modern hardware is powerful, so vertical scaling goes further than people think — but in interviews, horizontal scaling is the common pattern. Adding boxes only helps if clients know which server to talk to. Enter load balancing.
The client picks the server, usually after pulling a list from a service registry/directory and periodically syncing. Fast and efficient — no extra network hop per request, only periodic sync.
Nodes gossip to share cluster membership and status. The client hashes the key to find the shard,
then uses locally cached node info to pick the node. Wrong node? Redis replies MOVED.
The resolver returns a rotated list of IPs per request, so clients hit different servers — load balancing for free. Run two LBs in different regions and rotate via DNS to avoid a single point of failure.
When clients shouldn't know about multiple backends, or you have many uncontrolled clients needing fast updates, use a dedicated LB sitting between client and servers. It adds a hop but gives fast server-list updates and fine-grained routing control.
Routes on IP + port without inspecting packet content. Effectively a direct TCP connection between client and a randomly-selected backend.
Use for: WebSockets and other protocols needing persistent connections; high-performance, low-processing traffic.
Understands HTTP and inspects request content for smarter routing. Terminates incoming connections and opens new ones to backends.
Use for: HTTP traffic — API vs. web routing (like an API Gateway), sticky sessions by cookie, long polling.
LBs also monitor backend health and stop routing to a crashed server until it recovers — automatic failover, the basis of high availability. A TCP health check simply confirms the server accepts connections; an L7 health check makes an HTTP request and verifies a success code (200 vs. 500 or no response).
| Algorithm | How it distributes |
|---|---|
| Round Robin | Sequentially across servers |
| Random | Randomly across servers |
| Least Connections | To the server with fewest active connections |
| Least Response Time | To the fastest-responding server |
| IP Hash | Client IP picks the server (session persistence) |
Round robin / random suit stateless apps and naturally absorb new servers. For persistent connections (SSE, WebSockets), prefer Least Connections so one server doesn't slowly hoard every active connection.
F5 Networks BIG-IP — physical devices, can scale to 100s of millions of req/s.
HAProxy, NGINX, Envoy — more limited throughput.
AWS ELB/ALB/NLB, Google Cloud LB, Azure Load Balancer.
Global services distribute servers worldwide. A common pattern: multiple data centers per region (Amazon's "availability zones") so one building's failure doesn't take you down, replicated across cities.
The fix is data locality: keep the data needed to satisfy a query close together and close to the user. Some latency is unavoidable when users are simply far apart, but two strategies help.
Networks of servers in hundreds/thousands of cities ("edge locations"). If the edge can answer a request, response times are lightning-fast — the data is "just up the road." Works because of caching: data that changes rarely (images, video, static assets) is cached at the edge.
In interviews, use CDNs for highly cacheable data queried globally — e.g. caching search results to cut latency and backend load.
Partition data by region so each region holds only what's relevant. Uber: a Miami rider never books a New York driver. Bundle nearby cities into a local region, give each its own database and co-located servers. Queries are answered regionally (fast) against a local DB (very fast).
Servers crash, bits flip from solar flares, power is cut — and networks fail too: cables get cut, routers die, packets drop. Robust design plans for all of it.
The most basic hygiene: set a timeout, and retry if a request takes too long. Retries handle transient failures well — a temporarily slow server often succeeds on retry. Idempotent APIs are key so retries don't cause harm.
But retries are double-edged: hammering a failing system makes things worse. Add backoff — wait longer between each attempt — to give the system room to recover. Add jitter (randomness) so clients don't synchronize into a jackhammer of simultaneous retries.
Retries with side effects are dangerous — retrying a $10 charge could bill the user $20 or $2,000. Idempotent APIs produce the same result no matter how many times they're called. Reads (GET) are naturally idempotent; for writes, use an idempotency key — a unique request identifier.
For a payment where a user buys one item per day, set the key to userID + date.
The server checks whether it has already processed (or is processing) that key and runs it once.
Friendly APIs wait and return the result to all callers; less-friendly ones error that the request
already exists — either way, no double charge.
The defense against cascading failures. If a database goes cold and must boot one instance at a time, a firehose of retries (a "thundering herd") can pin every instance and prevent recovery. A circuit breaker protects against this:
Reject calls to failing services instead of waiting for timeouts.
Stop overwhelming a struggling service with more requests.
Automatically test recovery without full traffic.
Apply at: external/third-party API calls, database connections & queries, service-to-service calls in microservices, resource-intensive operations, and any network call that could fail or slow down. A great answer when an interviewer deep-dives on reliability, failure modes, or disaster recovery.
Networking is the foundation connecting every component in a distributed system. The field is vast, but these four areas cover most interviews:
IP addressing, DNS, and the TCP/IP model.
TCP vs. UDP, HTTP/HTTPS, WebSockets, gRPC.
Client-side LB and dedicated L4/L7 load balancers.
Regionalization, CDNs, and failure-handling patterns.
Score: 0 / 5