Skip to main content
Networking Protocols for System Design

Why Networking Matters

Every distributed system communicates over networks. Understanding networking is crucial for:
  • Latency optimization - Where does delay come from?
  • Protocol selection - HTTP vs WebSocket vs gRPC
  • Debugging issues - Why is my API slow?
  • Security design - TLS, firewalls, VPNs
Think of the network as the road system connecting buildings in a city. TCP is like certified mail — guaranteed delivery, in order, with a receipt. UDP is like shouting across the street — fast, no guarantee they heard you, but good enough for many situations. HTTP is like a form you fill out at a government office window: you submit a request, wait, and get a response. WebSockets are like a phone call — once connected, both sides talk freely. The reason you need to understand networking for system design is that the road system is always the bottleneck. The fastest database in the world is useless if the network between your service and the database adds 200ms of latency.
Practical tip: When debugging slow API calls, always measure where time is actually spent. Use the decomposition: DNS lookup + TCP handshake + TLS handshake + time-to-first-byte + transfer time. In most system design interviews, the latency bottleneck is not the protocol — it is geography (speed of light through fiber) or serialization. A senior engineer asks “where are the servers relative to the users?” before optimizing the protocol.

The OSI Model (Simplified)

DNS (Domain Name System)

DNS translates human-readable domain names to IP addresses.

DNS Resolution Flow

DNS Record Types

DNS in System Design

DNS TTL Matters: Low TTL (60s) = faster failover, more DNS queries. High TTL (3600s) = better caching, slower failover. Common: 300s (5 min)

TCP vs UDP

TCP (Transmission Control Protocol)

TCP vs UDP Comparison

When to Use What

Use TCP

  • Web applications (HTTP/HTTPS)
  • File transfers
  • Database connections
  • Email (SMTP, IMAP)
  • When data integrity matters

Use UDP

  • Live video/audio streaming
  • Online gaming
  • DNS queries
  • IoT sensors
  • When speed > reliability

HTTP/HTTPS

HTTP Request/Response

HTTP Methods

HTTP Status Codes

HTTP/1.1 vs HTTP/2 vs HTTP/3

HTTPS/TLS Handshake

WebSockets

WebSocket vs HTTP

WebSocket Use Cases

Real-time Chat

WhatsApp, Slack, Discord - instant message delivery

Live Updates

Stock prices, sports scores, notifications

Gaming

Multiplayer games, real-time player positions

Collaboration

Google Docs, Figma - live editing

WebSocket Scaling Challenge

WebSocket Scaling with Pub/Sub

WebSocket Implementation

Production-ready WebSocket server with connection management:

gRPC

gRPC vs REST

gRPC Communication Patterns

When to Use gRPC

Use gRPC

  • Microservices communication
  • Low latency requirements
  • Strong typing needed
  • Streaming data
  • Internal services

Avoid gRPC

  • Public APIs (browser clients)
  • Simple CRUD operations
  • Team unfamiliar with Protobuf
  • Debugging ease is priority

Long Polling vs SSE vs WebSocket

Network Latency Budget

Where Time Goes

Optimization Strategies

Interview Tip: When discussing latency, mention geographic distribution. “Users in Singapore accessing servers in US-East will have ~200ms RTT just from physics.”

Key Takeaways

Interview Deep-Dive Questions

What the interviewer is really testing: Whether you understand the full request lifecycle from browser to server and back — DNS, TCP, TLS, HTTP — and can systematically identify optimization opportunities at each layer.Strong Answer:
  • The 3-second first-page load breaks down into sequential network costs that only apply to the first request. Subsequent pages are fast because connections are reused and resources are cached. Let me walk through each phase.
  • DNS resolution: if the browser has no cache entry for your domain, it goes through the recursive resolver chain (browser cache, OS cache, ISP resolver, root servers, TLD servers, authoritative server). This can take 50-200ms depending on geography and cache state. Fix: use DNS prefetching (dns-prefetch link header), set reasonable TTLs on DNS records (300-600 seconds is typical — too low means frequent lookups, too high means slow failover).
  • TCP handshake: one round trip (SYN, SYN-ACK, ACK). For a user 100ms away from the server, that is 100ms. Fix: use a CDN so the TCP connection terminates at a nearby edge node rather than the origin server. Consider TCP Fast Open (TFO) which allows data in the SYN packet on subsequent connections.
  • TLS handshake: TLS 1.2 requires two additional round trips (200ms for a 100ms RTT user). TLS 1.3 reduces this to one round trip, and 0-RTT resumption eliminates it entirely for returning visitors. Fix: upgrade to TLS 1.3, enable session resumption, use OCSP stapling to avoid the client making a separate request to check certificate revocation.
  • HTTP request and response: the actual data transfer. If the page requires multiple resources (HTML, CSS, JavaScript, images), HTTP/1.1 loads them sequentially per connection (browsers open 6 parallel connections, but that is still a bottleneck). HTTP/2 multiplexes all requests over a single connection, eliminating head-of-line blocking at the HTTP layer. HTTP/3 (QUIC) goes further by eliminating head-of-line blocking at the transport layer.
  • Server processing: Time-to-first-byte (TTFB) depends on server-side processing. If the server needs to query a database, render a template, and assemble the response, that adds latency. Fix: server-side caching, precomputed pages for common routes, edge-side rendering.
  • Total optimization: DNS (50ms saved with prefetch) + TCP (100ms saved with CDN) + TLS (100ms saved with TLS 1.3) + HTTP multiplexing (200ms saved with HTTP/2) + server-side caching (500ms saved with CDN cache hit) can bring the 3-second load down to under 500ms.
  • Example: Cloudflare’s performance measurements show that switching from TLS 1.2 to TLS 1.3 saves one full RTT per new connection. For users in Australia connecting to US servers (200ms RTT), that is a 200ms improvement on every first visit. Combined with their CDN edge nodes in Sydney, the TCP+TLS cost drops from 600ms to under 50ms.
Follow-up: The site uses HTTP/2 and a CDN, but mobile users in India still report slow loads. Desktop users in the same region are fine. What networking factors specific to mobile could explain this?Mobile networks add several latency sources: (1) Radio resource allocation — on LTE/5G, the device must negotiate a radio channel before any data can flow, adding 50-100ms. (2) Higher RTTs on cellular networks — typical LTE RTT is 30-50ms even to nearby towers, versus 5-10ms for wired broadband. (3) TCP slow start interacts badly with mobile — high RTT means the congestion window grows slowly, so large resources take many round trips to fully transfer. (4) Packet loss on mobile is higher, causing TCP retransmissions. Fix: aggressive resource compression, smaller initial page payloads (aim for under 14KB to fit in the first TCP congestion window), lazy loading of non-critical resources, and consider QUIC/HTTP3 which handles packet loss better than TCP because it avoids head-of-line blocking across streams.
What the interviewer is really testing: Whether you can make nuanced protocol decisions based on actual requirements rather than hype, and whether you understand the operational implications beyond raw performance.Strong Answer:
  • gRPC is not universally better than REST — it is better for specific use cases, and it comes with operational costs that are easy to underestimate. The decision should be driven by concrete pain points, not benchmarks.
  • When gRPC makes sense: (1) High-throughput internal service communication where the protobuf binary encoding saves significant bandwidth (a 1KB JSON payload might be 300 bytes in protobuf — at millions of requests per second, that bandwidth savings is real). (2) Strict API contracts are needed — protobuf schemas enforce types at compile time, catching breaking changes before deployment. (3) You need streaming (server-streaming, client-streaming, or bidirectional streaming) — gRPC has first-class streaming support, while REST over HTTP/1.1 does not. (4) Latency-sensitive internal paths where JSON parsing overhead matters (protobuf deserialization is 2-10x faster than JSON parsing).
  • When REST is still the right choice: (1) Public-facing APIs — browsers do not natively support gRPC (you need gRPC-Web or a proxy), and developer experience with REST is far more accessible. (2) Services that are called infrequently — the performance difference is negligible at low volume. (3) Teams without protobuf experience — the learning curve is real and affects velocity.
  • Operational costs people underestimate: (1) Debugging is harder — binary protobuf payloads are not human-readable in packet captures or logs. You need tools like grpcurl or Postman’s gRPC support. With REST, you can curl an endpoint and read the JSON response. (2) Load balancing is more complex — gRPC uses HTTP/2 with long-lived connections. A standard L4 load balancer will route all requests from one connection to one backend. You need L7 (application-layer) load balancing that understands HTTP/2 frames, or client-side load balancing. (3) Schema evolution requires discipline — adding a field to a protobuf message is backward-compatible, but removing or renumbering a field is a breaking change that can cause silent data corruption. (4) Monitoring and tracing middleware needs to understand gRPC status codes (which are different from HTTP status codes).
  • My recommendation for the team: introduce gRPC selectively on the highest-traffic internal paths first. Keep REST for public APIs and low-volume internal services. Run both protocols through the same service mesh so you get consistent observability regardless of protocol.
  • Example: Google uses gRPC internally for almost all service-to-service communication (it was built for this purpose), but their public APIs (Maps, Gmail, etc.) offer REST endpoints because developer adoption matters more than protocol efficiency for external consumers. Internally, they report that gRPC’s streaming support was a bigger factor than raw performance in their adoption decision.
Follow-up: Your team adopts gRPC for the critical path between the API Gateway and the Order Service. Requests are being unevenly distributed — one Order Service instance is getting 80% of traffic while three others are idle. What is happening?This is the classic gRPC load balancing problem. gRPC uses HTTP/2, which multiplexes all requests over a single long-lived TCP connection. If the API Gateway opens one connection to each backend, the L4 load balancer assigned the connection to one backend and all subsequent requests flow through that same connection. Solutions: (1) Use L7 load balancing (Envoy, nginx with gRPC support) that can distribute individual gRPC requests across backends, not just connections. (2) Use client-side load balancing where the API Gateway maintains connections to all backends and round-robins requests itself (gRPC libraries support this natively with name resolvers). (3) If using Kubernetes, use a service mesh like Istio which handles per-request load balancing transparently.
What the interviewer is really testing: Whether you understand networking fundamentals at a practical level and can connect low-level protocol behavior to high-level system design decisions.Strong Answer:
  • The three-way handshake establishes a TCP connection: (1) Client sends SYN with an initial sequence number. (2) Server responds with SYN-ACK, acknowledging the client’s sequence number and providing its own. (3) Client sends ACK, acknowledging the server’s sequence number. The connection is now established and data can flow.
  • This takes one round trip (the SYN goes out, SYN-ACK comes back, ACK goes out with or before the first data packet). For system design, this means every new TCP connection costs at minimum one RTT before any application data is exchanged.
  • Why this matters for system design: (1) Connection pooling is critical for microservices. If Service A calls Service B 1000 times per second and opens a new connection each time, you are paying 1000 handshakes per second. At 1ms RTT within a datacenter, that is tolerable but wasteful. At 100ms RTT across regions, that is 100 seconds of cumulative handshake time per second of operation — a disaster. Connection pools reuse established connections, amortizing the handshake cost. (2) TCP slow start means even after the handshake, the connection starts with a small congestion window (typically 10 segments, or ~14KB). It takes multiple round trips to ramp up to full throughput. This is why large file downloads are slow at the beginning and why serving a 100KB response over a fresh connection takes longer than serving it over a warm connection. (3) Keep-alive connections (HTTP keep-alive, gRPC persistent connections) avoid repeated handshakes. The trade-off is that each open connection consumes memory on both client and server (kernel buffers, file descriptors). A server with 100K idle keep-alive connections can consume significant memory. (4) CDNs and edge proxies work partly by terminating TCP connections close to the user. The handshake RTT between the user and the CDN edge is 5ms instead of 150ms to the origin. The CDN can maintain a warm, pre-established connection pool to the origin.
  • UDP skips the handshake entirely, which is why DNS uses UDP for small queries (the entire query and response fit in one round trip), and why QUIC (the transport under HTTP/3) uses UDP with its own connection establishment that can be done in 0-RTT for returning visitors.
  • Example: When Cloudflare analyzed their traffic, they found that 40% of the latency for typical web requests was TCP and TLS handshake overhead. By moving their edge nodes closer to users and enabling TLS 1.3 with 0-RTT, they eliminated most of this overhead for repeat visitors. This is a direct system design implication of the three-way handshake cost.
Follow-up: A service behind your load balancer is running out of ephemeral ports and you see thousands of connections in TIME_WAIT state. What is happening and how do you fix it?TIME_WAIT is a TCP state where a closed connection lingers for 2x the maximum segment lifetime (typically 60 seconds on Linux) to ensure delayed packets from the old connection do not corrupt a new connection on the same port. If a service opens and closes many short-lived connections rapidly (e.g., a microservice making thousands of HTTP calls per second without connection pooling), it exhausts the ephemeral port range (typically 28,232 ports on Linux). Fixes: (1) Use connection pooling — this is the primary fix. Reuse connections instead of opening new ones. (2) Increase the ephemeral port range via net.ipv4.ip_local_port_range. (3) Enable net.ipv4.tcp_tw_reuse to allow reusing TIME_WAIT sockets for new outbound connections (safe for client-initiated connections). (4) Never enable tcp_tw_recycle — it breaks NAT and was removed from Linux 4.12. The root cause is almost always missing connection pooling.