Networking, from
a packet to a page.
Every system design leans on the network, and interviewers love to probe it: TCP vs UDP, what DNS actually does, why HTTP/3 exists, and why the same request is fast next door and slow across the ocean. Here's the stack, from the wire up to HTTPS, and the one number that dominates it all.
The layered model
Networking is built in layers, each solving one problem and handing off to the next. You don't need the full seven-layer OSI model; the practical stack is four layers, and every request climbs it.
Why layer at all? Separation of concerns: each layer trusts the one below and offers a clean service to the one above, so HTTP doesn't care whether it's on fiber or Wi-Fi, and IP doesn't care whether it's carrying TCP or UDP. This lets each evolve independently — which is exactly how HTTP/3 could swap TCP for a new transport without changing the app layer.
All seven layers, and what actually lives at each
The four-layer stack above is the working model. The textbook map — and the one interviewers name-check — is the seven-layer OSI model, standardized by ISO in the 1980s. Its lasting value isn't as a description of the internet (it isn't one, as we'll see); it's as a vocabulary. When a colleague says "that's an L4 load balancer" or "we terminate TLS at L7" or "this is a layer-2 problem," they're pointing at a number on this list, and everyone knows roughly which box to open.
Think of it as a message crossing Wi-Fi, then copper, then a fiber trunk under an ocean, then a dozen routers built by a dozen vendors — and still arriving intact. That works because no single piece of the network is allowed to know too much. Each layer does exactly one job and talks only to its immediate neighbours above and below.
| # | Layer | What actually lives there | Unit |
|---|---|---|---|
| 7 | Application | The protocol your program speaks — HTTP, DNS, gRPC, SMTP, WebSocket, SSH | Message |
| 6 | Presentation | Putting data in a format both sides agree on — character encoding, serialization, compression, encryption (where OSI would file TLS) | — |
| 5 | Session | Managing a conversation between two endpoints over time — establish, checkpoint, resume | — |
| 4 | Transport | End-to-end, process-to-process delivery: TCP (reliable, ordered), UDP (best-effort), port numbers | Segment / datagram |
| 3 | Network | Addressing and routing across many hops: IP, ICMP, BGP-learned routes, NAT | Packet |
| 2 | Data link | Framing bits and moving them across one local hop: Ethernet, Wi-Fi framing, MAC addresses, ARP, switches | Frame |
| 1 | Physical | The actual signal: voltages on copper, light pulses in fiber, radio in the air — plus connectors, cable, and timing | Bit |
Notice how the scope narrows as you descend: layer 4 is responsible for the whole journey between two processes, layer 3 for the whole journey between two machines, and layer 2 for exactly one hop. A router forwarding your packet has no idea what your application was trying to say; your application has no idea whether the last hop was Wi-Fi or fiber. That mutual ignorance is the design, not a shortcoming.
Encapsulation: boxes inside boxes
The mechanism that makes this division of labour actually work is encapsulation. Going down the stack on the sending side, each layer takes whatever it received from above, treats it as an opaque payload, and wraps it in its own header — a small block of control information meant only for that layer's counterpart at the other end. Your bytes get a TCP header (ports, sequence number, ACK, window), that whole bundle gets an IP header (source and destination addresses, TTL), and that gets an Ethernet header and trailer before becoming a signal on the wire.
On the receiving side the process runs exactly backwards — decapsulation. The physical layer recovers raw bits; the link layer strips its header and hands the contents up; the network layer strips its header and hands the contents up; and so on until only the original application data remains. Each layer opens exactly one envelope. The network layer never reads the transport header; the transport layer never reads your payload.
Two details worth carrying into an interview. First, the L2 header is hop-scoped: source and destination MAC addresses are rewritten by every router along the path, while the IP header's source and destination stay fixed end to end. Second, encapsulation is why MTU matters — headers eat into the 1500-byte frame, so a tunnel (VPN, VXLAN) that adds another set of headers shrinks the usable payload and causes the classic "small requests work, large ones hang" bug.
Where OSI diverges from the stack the internet actually runs
Here's the part most explanations skip: OSI was a competing protocol suite, and it lost. ISO didn't just publish a reference model; it published protocols to fill each layer. The internet meanwhile ran on TCP/IP, whose own reference model — written down in RFC 1122 — has four layers: link, internet, transport, application. TCP/IP shipped, OSI's protocols largely didn't, and what survived was the numbering.
So the map doesn't quite fit the territory:
| OSI says | The internet actually does |
|---|---|
| 7 distinct layers | 5 in practice (application, transport, network, link, physical) — or 4 if you use RFC 1122, which folds physical into link. |
| Session (5) and presentation (6) are layers | They have no home. Those concerns were absorbed into application protocols and libraries — HTTP does its own content negotiation, cookies do its session state, JSON/protobuf do its presentation. |
| Encryption belongs at layer 6 | TLS sits above TCP and below HTTP, so people variously call it L6, L5, or "layer 4.5." Architecturally it's an application-layer protocol that other application protocols run over. |
| Layers don't peek at each other | They leak constantly. NAT is an "L3 device" that rewrites L4 port numbers. An "L7 load balancer" terminates TCP and TLS and re-originates a new connection. MPLS is nicknamed "layer 2.5" precisely because it fits nowhere. |
| Transport is fixed in the kernel | QUIC implements streams, reliability, and congestion control in user space on top of UDP — a transport built inside what OSI would call the application layer. See TCP vs UDP. |
The right posture is therefore: use the layer numbers as shared shorthand, and don't defend the model's edges. If an interviewer asks "what layer is TLS?", the strong answer names the ambiguity and explains why it exists, rather than confidently picking a number.
Which layers you actually touch
Day to day, most application and backend engineers live almost entirely at layers 7 and 4. Layer 7 is status codes, headers, timeouts, retries, idempotency, gRPC deadlines, and DNS names. Layer 4 is ports, TCP vs UDP, keep-alive, connection pools, socket options, and whether your load balancer operates on connections or requests.
Layer 3 shows up the moment you touch infrastructure: CIDR blocks, VPC subnets, route tables, security groups, NAT gateways, MTU, and traceroute. Layers 2 and 1 generally belong to your cloud provider or datacenter team — you meet them when something is broken (a duplex mismatch, a flapping cable, an MTU mismatch on a VPN that hangs only on large payloads). And layers 5 and 6 you effectively never touch as distinct layers at all, which is the clearest evidence that the seven-layer model is a teaching device rather than an implementation.
The model earns its keep when something breaks: go bottom-up and stop at the first failure. ping proves L3 reachability; traceroute shows where the path dies; nc -vz host port proves L4 (a port is open and accepting); openssl s_client -connect host:443 proves the certificate and TLS negotiation; curl -v proves L7. "It's slow" and "it's broken" become answerable questions the moment you know which layer stopped working.
Want to see the layers move? The DNS journey lab walks a name resolution end to end, the TLS handshake lab steps through the layer that OSI can't place, and the TCP congestion lab shows what layer 4 does when the network pushes back. For where the stack meets your machine — sockets, file descriptors, the kernel/user-space boundary — see the OS Fundamentals and Linux Internals handbooks.
The OSI model, layer by layer
IP: addressing & routing
The Internet Protocol gives every device an IP address and breaks data into packets, each stamped with source and destination addresses. Packets travel hop by hop: routers read the destination and forward each packet toward it, with no guarantee of order, timing, or even delivery — IP is deliberately simple and "best-effort." Reliability, if you want it, is added above by TCP.
Two practical notes interviewers like: addresses are scarce (IPv4) so private networks use NAT to share one public address among many devices — which is why most machines have no public IP and can't be directly reached (relevant to DNS, WebRTC, and firewalls). And there's no central map; routing emerges from routers exchanging reachability info (BGP at internet scale). IP's job is just "get this packet closer to its destination."
TCP vs UDP
The transport layer's fork in the road — reliability, or speed.
Both run on IP; they differ in what they promise. TCP is a connection-oriented, reliable, ordered byte stream: it sets up a connection, numbers bytes, acknowledges receipt, retransmits losses, and delivers data in order. UDP is connectionless and unreliable: fire-and-forget datagrams with no ordering, no retransmission, no setup — just fast.
| TCP | UDP | |
|---|---|---|
| Guarantees | Reliable, in-order, connection | None — best effort |
| Overhead | Handshake + acks + retransmit | Minimal |
| Best for | Web, APIs, files — correctness matters | Video/voice, gaming, DNS — timeliness matters |
The rule: use TCP when every byte must arrive correctly and in order; use UDP when a late packet is worse than a lost one (real-time media would rather skip a dropped frame than wait for a retransmit). This exact tradeoff is why video calls use UDP and file downloads use TCP.
The handshake & head-of-line blocking
TCP's reliability starts with the three-way handshake: client sends SYN, server replies SYN-ACK, client sends ACK — synchronizing sequence numbers and confirming both directions work. The cost: a full round trip before any data, on top of which TLS adds more (section 07). This is why reusing connections and reducing round trips is a recurring performance theme.
TCP's in-order guarantee has a dark side: head-of-line blocking. Because data must be delivered in order, a single lost packet stalls everything behind it until it's retransmitted — even data that already arrived waits. This is a real limitation you'll cite repeatedly: it's why HTTP/1.1 pipelining failed, part of why HTTP/2 still suffers at the TCP layer, and precisely what HTTP/3 was built to escape.
Every new TCP connection costs a round trip to handshake (plus TLS). Across the planet a round trip can be 100–200ms, so cutting connections and round-trips — keep-alive, connection pooling, HTTP/2 multiplexing, CDNs — is often the biggest latency win.
DNS: names to addresses
You type a name; computers need an IP. DNS is the internet's phone book, and it's distributed by design. Your machine asks a recursive resolver, which walks a hierarchy: a root server points to the .com TLD servers, which point to the domain's authoritative nameserver, which returns the IP. Three referrals, one answer.
That would be slow every time, so DNS leans hard on caching: every record carries a TTL, and resolvers cache answers for that long, so the vast majority of lookups never touch the hierarchy. The interview-worthy consequences: a DNS change isn't instant (it "propagates" only as old TTLs expire), and DNS doubles as a coarse load-balancer and failover mechanism (returning different IPs by region or health). For the full mechanism, see the Design DNS walkthrough.
HTTP: 1.1 → 2 → 3
On top of transport sits HTTP, the app protocol of the web — and its evolution is a story of killing head-of-line blocking. HTTP/1.1 sends one request at a time per connection (browsers open several connections to compensate); a slow response blocks the connection behind it. HTTP/2 adds multiplexing: many requests share one connection as independent streams, plus header compression — solving request-level blocking. But it still runs on TCP, so a lost packet still stalls all streams at the transport layer.
HTTP/3 takes the radical step of moving off TCP entirely, onto QUIC — a new transport built on UDP that implements reliability and streams itself, so a lost packet only blocks its own stream, not the others. QUIC also folds the connection and TLS handshakes together to cut setup round trips. Each version chips away at the same enemy: waiting.
| Version | Key change | Head-of-line blocking |
|---|---|---|
| HTTP/1.1 | One request per connection | At the request level |
| HTTP/2 | Multiplexed streams, header compression | Gone at request level, remains at TCP level |
| HTTP/3 | QUIC over UDP; faster handshakes | Gone — per-stream, no TCP-level stall |
TLS & HTTPS
HTTPS is HTTP over TLS, and TLS gives three guarantees. Encryption: a network eavesdropper can't read the traffic. Integrity: tampering is detected. Authentication: the server proves its identity via a certificate signed by a trusted authority, so you're really talking to the site you think you are (thwarting impersonation).
Mechanically, a TLS handshake follows the TCP handshake: the parties agree on cipher suites, the server presents its certificate, and they establish a shared session key using asymmetric crypto, after which fast symmetric encryption protects the data. The cost is extra round trips on top of TCP — which is why TLS session resumption, and QUIC folding TLS into the transport handshake, matter for latency. The takeaway for interviews: HTTPS = confidentiality + integrity + server identity, at the price of a handshake.
Latency vs bandwidth
The most important networking intuition: bandwidth and latency are different, and for interactive requests latency usually wins. Bandwidth is how much data per second (the pipe's width); latency is how long each round trip takes, bounded by distance and the speed of light in fiber. A fatter pipe doesn't shorten the wire.
And crucially, many operations are sequential round trips: DNS lookup, TCP handshake, TLS handshake, then the actual request — several full round trips before your data even starts, each paying the distance cost. That's why a request to a server across the ocean feels slow no matter your bandwidth, and why the biggest wins are reducing round trips (keep-alive, HTTP/2/3, caching) and reducing distance (CDNs, edge, regional deployment). When someone asks "how do I make this faster?", the network answer is almost always: fewer round trips, closer servers.
Round-trip time (RTT) is set by physics; you can't optimize the speed of light. So you count round trips and shorten distance. A single cross-planet RTT is ~150ms — do it four times sequentially to set up a request and you've spent half a second before any real work.
Three numbers, not two: bandwidth, throughput, latency
This section is titled "latency vs bandwidth" because that's the comparison people reach for — and it's the right first cut. But there's a third number hiding inside "bandwidth," and separating it out is where the real understanding lives:
| Bandwidth | Throughput | Latency | |
|---|---|---|---|
| Is | Capacity — what the link could carry | Achieved rate — what you actually get | Delay — how long one trip takes |
| Unit | bits/sec (or RPS a fleet is provisioned for) | bits/sec, requests/sec (measured) | milliseconds (report p99, not the mean) |
| Analogy | Lanes on the highway | Cars per hour actually crossing | How long your car takes to arrive |
| Raised by | A fatter link; more servers, workers, connections | Removing whatever the current bottleneck is | Less distance, fewer round trips, less queuing |
Throughput is always ≤ bandwidth, and the gap is the interesting part. A gigabit link delivering 5 Mbps isn't a broken link — it's a small TCP window, or packet loss, or a slow origin server, or a single-threaded client. Bandwidth is a ceiling somebody sold you; throughput is a measurement you take.
The same three words scale up to whole systems, which is where teams talk past each other. "The checkout flow is slow" splits into two different tickets: one engineer profiles a single request and trims milliseconds off a database call (a latency fix), the other adds servers and widens a connection pool (a throughput fix). Adding capacity makes no individual request faster — it only lets more of them run side by side. Naming which number you're moving is the first step to actually fixing it.
Bandwidth is how wide the pipe is. Throughput is how much is really flowing through it. Latency is how long it takes one drop to get from end to end. You buy bandwidth, you measure throughput, and users feel latency.
The speed-of-light floor
Latency has a hard physical bottom that no amount of engineering removes. Light travels ~300,000 km/s in vacuum, but in fiber the refractive index (~1.5) slows it to roughly 200,000 km/s — about 5 microseconds per kilometre, or ~1 ms of round-trip time per 100 km of distance. Then reality adds to it: cables follow coastlines, rights-of-way, and existing trenches rather than great circles (typically 1.5–2× the straight-line distance), and every router, switch, and last-mile hop adds processing and queuing.
| Route | Great-circle distance | RTT floor in fiber | Typical measured RTT |
|---|---|---|---|
| New York ↔ San Francisco | ~4,100 km | ~41 ms | ~60–70 ms |
| New York ↔ London | ~5,600 km | ~56 ms | ~70–80 ms |
| London ↔ Singapore | ~10,800 km | ~108 ms | ~160–180 ms |
| New York ↔ Sydney | ~16,000 km | ~160 ms | ~200–240 ms |
| Same city / same AZ | < 50 km | < 1 ms | ~0.5–2 ms |
Read the third column as a budget you cannot negotiate. If your origin is in Virginia and your user is in Sydney, every sequential round trip costs ~200 ms before your code executes a single line. Upgrading the user's connection from 100 Mbps to 1 Gbps changes none of those numbers. Moving the bytes closer — a CDN edge, a regional replica, a read replica in-region — changes all of them.
Why more bandwidth stops helping
There's a well-known measurement result behind this, popularized in Ilya Grigorik's High Performance Browser Networking: as connection bandwidth rises from 1 Mbps to about 5 Mbps, page-load time improves substantially; past roughly 5–10 Mbps the curve flattens and further bandwidth buys almost nothing. Reducing RTT, by contrast, improves page load close to linearly — shave 20 ms off the round trip and the page gets faster at every bandwidth tier.
Two mechanisms explain it. First, a web page isn't one big transfer; it's dozens of small objects, and the work is dominated by sequential DNS, TCP, TLS, and request round trips — pure latency, immune to the pipe's width. Second, TCP slow start means a fresh connection doesn't use the bandwidth you have. The initial congestion window is 10 segments (RFC 6928), roughly 14 KB, and it can only double once per round trip:
At a 150 ms RTT that's over a second spent ramping up — on a 1 Gbps link that never gets used. Watch it happen in the TCP congestion lab.
The practical corollary: for anything under a few hundred KB, you are latency-bound, not bandwidth-bound. Bandwidth only becomes the binding constraint for sustained bulk transfer — video, backups, dataset syncs — where the connection has time to reach full speed.
Bandwidth-delay product: how much has to be in flight
The two numbers meet in one formula. The bandwidth-delay product (BDP) is how many bytes must be in flight, unacknowledged at any instant to keep a pipe completely full:
If the sender's or receiver's window is smaller than the BDP, throughput is capped at window ÷ RTT — the link's rated bandwidth becomes irrelevant.
This is the classic long fat network (LFN) problem, and it has a famous concrete case. TCP's original window field is 16 bits, so the maximum unscaled window is 65,535 bytes. On a 100 ms transatlantic path that caps a single connection at 65,535 ÷ 0.1 s ≈ 655 KB/s — about 5.2 Mbps, no matter whether the link is 100 Mbps or 100 Gbps. RFC 7323 window scaling exists precisely to lift that ceiling, and it's why bulk cross-ocean transfers still need tuned socket buffers or parallel streams. The runnable code in the next section computes the BDP for numbers you choose.
Queuing: the hidden latency knob called utilization
The last piece is the one that surprises people: latency is not constant — it's a function of how loaded the system is. Below capacity, latency and throughput barely interact; there's slack, so pushing more requests through doesn't make any single one wait. Push toward the limit and requests stop being served immediately and start queuing — and queuing delay doesn't grow gently.
For a simple queue, average response time relates to service time and utilization ρ as latency ≈ service_time ÷ (1 − ρ). That denominator is the whole story:
| Utilization | Latency multiplier | What it feels like |
|---|---|---|
| 50% | 2× | Comfortable — plenty of headroom |
| 70% | 3.3× | The usual capacity-planning target |
| 80% | 5× | Tail latency (p99) starts getting ugly |
| 90% | 10× | "The site is slow" tickets, with CPU graphs that look fine |
| 99% | 100× | Effectively an outage; the queue never drains |
That's the hockey stick: flat for a long stretch, then near-vertical. It explains why a link "only 80% utilized" can feel awful, why teams provision for ~60–70% rather than 95%, and why bufferbloat hurts — oversized router buffers convert what should be a dropped packet into hundreds of milliseconds of extra delay. It also explains the batching tradeoff: collecting several requests before processing them together (GPU inference, database writes, log shipping) raises throughput and adds latency to each request, because the first arrival waits for the rest. That's a knob, not a bug — but only turn it once you know which number you're trying to move. Load-shedding and queue limits are the other half of the answer; see the load balancer simulator.
Little's Law says requests in flight = throughput × latency. The bandwidth-delay product says bytes in flight = bandwidth × RTT. They are the same equation: a network link is just a queueing system whose "requests" are bytes. Once you see that, the three numbers stop being separate facts — capacity, achieved rate, and delay are three views of one relationship, and you can never fix all three at once.
Latency vs throughput, in two minutes
It's just multiplication. A small request's time is its round trips times the RTT (transfer is negligible), so the two levers are fewer round trips and shorter RTT — never a fatter pipe:
Doubling bandwidth changes 600.08ms to 600.04ms — nothing. The runnable version below proves the pipe doesn't matter and computes the bandwidth-delay product.
Prove that bandwidth doesn't fix latency
A small request's time is round trips × RTT — the transfer is a rounding error. This computes it three ways: a cold cross-ocean request paying four sequential round trips (600ms), the same connection kept warm (150ms), and the same trips via a nearby CDN edge (40ms). Then it doubles the bandwidth and shows the request time barely moves — because it's latency-bound, not bandwidth-bound. Finally it computes the bandwidth-delay product: how much data must be in flight to fill a fat, long pipe. Change the round trips, RTT, or bandwidth.
Quick answers
TCP vs UDP?
TCP is a reliable, ordered, connection-oriented byte stream (retransmits, in-order) — good for web/APIs/files. UDP is connectionless and unreliable but fast — good for real-time media, gaming, DNS, where a late packet is worse than a lost one.
The TCP handshake?
SYN → SYN-ACK → ACK: synchronizes sequence numbers and confirms both directions work, costing a full round trip before data flows (plus TLS on top for HTTPS).
Head-of-line blocking?
One delayed item stalls everything behind it. TCP's in-order rule means a lost packet blocks later data; HTTP/2 fixed request-level blocking, HTTP/3 (QUIC/UDP) removes the TCP-level version.
Latency vs bandwidth?
Bandwidth is data per second; latency is round-trip time bounded by distance. Many requests need several sequential round trips, so cutting round trips and distance beats a fatter pipe for interactive traffic.
What are the 7 OSI layers?
Physical, data link, network, transport, session, presentation, application — bottom to top. In practice the internet runs a 5-layer TCP/IP stack (application, transport, network, link, physical): session and presentation have no real home, and their concerns were absorbed into application protocols and libraries. Treat the numbers as shared vocabulary ("L4 load balancer", "L7 routing"), not as a description of real implementations.
What is encapsulation?
Going down the stack, each layer wraps what it got from above in its own header: your bytes get a TCP header (ports, sequence numbers), that gets an IP header (source and destination addresses), that gets an Ethernet header and checksum. Boxes inside boxes. The receiver decapsulates in exact reverse, and each layer opens only its own envelope — the router never reads your payload.
Bandwidth vs throughput vs latency?
Bandwidth is capacity — what the link could carry. Throughput is the rate you actually achieve, always less than or equal to bandwidth, and limited by whatever the real bottleneck is (window size, loss, a slow server). Latency is the delay for one trip. You buy bandwidth, you measure throughput, and users feel latency.
Why does high utilization make things slow?
Because requests queue. Response time scales roughly as service time divided by (1 minus utilization), so 50% load costs about 2x, 90% costs about 10x, and 99% costs about 100x. The curve is flat then near-vertical, which is why capacity planning targets 60-70% rather than 95% and why a system can feel broken while CPU graphs still look fine.
Prefer a video walkthrough?
Explore the topic
See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.
More Handbooks
- The System Design Fundamentals HandbookThe load-bearing ideas behind every distributed system — the CAP theorem and consistency models, concurrency and locking, partitioning and replication, and consensus and coordination — each tied to a real worked design you can study interactively.Read →
- CAP Theorem & Consistency ModelsWhat a distributed system can promise when the network splits — CP vs AP, why "CA" is a myth, PACELC, and the full spectrum from linearizable to eventual consistency. Part of System Design Fundamentals.Read →
- Partitioning, Sharding & ReplicationHow one dataset becomes many — range vs hash partitioning, consistent hashing and virtual nodes, hot partitions, replication topologies, replication lag, and quorums. Part of System Design Fundamentals.Read →
- Consensus, Transactions & CoordinationHow nodes that can crash still agree on one truth — majority quorums, Raft and Paxos, leader election, two-phase commit vs the saga pattern, and idempotency for exactly-once effects. Part of System Design Fundamentals.Read →
- The Kubernetes HandbookThe one idea under all the YAML — declare desired state, and a control loop makes reality match. Covers the orchestration problem, pods, deployments and replicasets, services and networking, the reconciliation loop and self-healing, the scheduler, config/secrets and health probes, autoscaling, and when you actually need Kubernetes.Read →
- The Observability HandbookSeeing inside production — monitoring vs observability, the three pillars (metrics, logs, traces) and what each answers, structured logging, metric types and the cardinality trap, distributed tracing, the golden signals and SLIs/SLOs/error budgets, alerting on symptoms not causes, and correlating all three during an incident.Read →