Networking
Every "the app is down" incident is really a networking incident in disguise, so a DevOps engineer has to understand how data actually travels. This chapter rebuilds the two networking-fundamentals videos into a workshop: first you understand the building blocks — IP addresses, subnets, CIDR, and ports — and the full journey of data through the OSI model, then you get quizzed the way an interviewer would, and finally you face the senior connectivity scenarios.
Networking answers one question: how does a request travel from your device to a server and back? Four building blocks describe where things are, and one model describes how the data moves. The building blocks are the IP address (a unique number for each device), the subnet (a slice of a network, isolated for security), the CIDR range (how you say how many addresses a subnet has), and the port (a unique number for one application on a machine). The model is the OSI model, which describes the journey of your data as it passes down through seven layers on the way out and back up through them on the way in.
Two things happen before a request is even sent: DNS resolution turns a name like google.com into an IP address, and the TCP handshake confirms the server is willing to talk. And the one heuristic that saves you on-call more than any other: "connection refused" means you reached the host but nothing is listening (look at the process), whereas "connection timed out" means something is silently dropping your packets (look at the firewall and the route).
- ① Theory — the concepts (Networking + OSI Model)
- The IP address — a unique number for every device
- Subnets — slicing a network for isolation
- CIDR — how you size a subnet
- Ports — addressing one application on a machine
- Before the request — DNS resolution and the TCP handshake
- The OSI model — the journey of data in seven layers
- ② Interview Q&A — the concepts you must be able to explain
- ③ Scenario drills — the senior connectivity layer (16)
The IP address — a unique number for every device
An IP address is a very simple idea: it is a unique address given to a device that is connected to a network.
Imagine a house with a Wi-Fi network created by a router, and two people living there, each with two devices, so four devices are connected in total. One day one of those devices is used to make a payment, and you want to know which one, or you want to block one child's device from Instagram, or monitor one particular device's activity. You cannot do any of that if the devices have no unique identity — you would end up blocking all of them. So each device needs a unique identification number, and that number is its IP address. The same need scales up: a home has four devices, but a school or office network might have ten or twenty thousand, so you need a proper, consistent standard for handing out these unique numbers.
The standard used for this is IPv4 (there is also a newer standard, IPv6, which we will set aside for now). An IPv4 address is written as four numbers separated by dots, such as 192.168.12.4, and you can see your own by running ifconfig or ipconfig. Each of the four numbers can range only from 0 to 255, and understanding why matters later when we get to subnets and CIDR.
The reason each number stops at 255 is that a computer does not understand decimal numbers — it understands bits. An IPv4 address is really four bytes, or 32 bits, and each byte is eight bits. When you write 192, the computer stores it as the eight bits 11000000, which is 2⁷ + 2⁶ = 128 + 64 = 192. If every one of the eight bits were set, the value would be 2⁷ + 2⁶ + … + 2⁰ = 255, and that is the largest a single byte can hold. So a value like 192.600.12.254 is not a valid IP address, because 600 cannot fit in one byte.
Subnets — slicing a network for isolation
A subnet is exactly what the name suggests — a sub-network, a slice of a bigger network that you carve out on purpose.
Picture an office with a single free Wi-Fi network that anyone can join. One day an employee visits a malicious website, a hacker gets into that one device, and because every device is on the same network, the hacker can now reach all of them — including servers holding payroll, financial data, and other sensitive files. The whole company network is compromised from a single click. This is the problem subnetting solves. You take one network — for example, a VPC in AWS with 65,000 addresses — and split it into separate parts: one secure subnet used only by the finance team for sensitive information, and one free subnet that anyone can join. Now a hacker who compromises a device on the free subnet is contained there and cannot reach the finance subnet.
So the advantages of a subnet are security, privacy, and proper isolation, and you can create subnets in any network, even your home Wi-Fi. There are also two types of subnet, and the only difference between them is internet access:
- A public subnet has access to the internet.
- A private subnet does not have access to the internet.
On a cloud provider you make a subnet public by attaching a route table to it whose route points to an internet gateway; without that, the subnet is private. You do not need to memorise that mechanism yet — the fundamental point is simply that a public subnet can reach the internet and a private subnet cannot.
CIDR — how you size a subnet
When you split a network into subnets, you have to say how many addresses each subnet gets. CIDR is how you say it, and the calculation behind it is simpler than people expect.
Suppose you created a VPC — which is just a private network — with the range 172.16.0.0/16, giving you about 65,000 addresses, and now you want a finance subnet with only 256 addresses and a free subnet with the rest. You express the size of a subnet with a CIDR range, written as an IP address followed by a slash and a number, such as 172.16.3.0/24. That trailing number tells you how many addresses the subnet contains, using one simple formula.
Remember that an IP address is 32 bits. The number after the slash is how many of those 32 bits are fixed (the same for every address in the subnet); the bits that are left over are free to vary, and each free bit doubles the count. So the number of addresses is 2 to the power of (32 minus the slash number):
/24 gives 256 addresses, a /26 gives 64, and a /8 gives about 16 million.Working through the common cases: a /24 means 24 bits are fixed and 8 are free, so 2⁸ = 256 addresses; a /16 gives 2¹⁶ ≈ 65,000; and a /8 gives 2²⁴, about 16 million. These three are so common they have names — /8 is class A, /16 is class B, and /24 is class C — but you will also see values like /26, /27, and /29. Do not panic when you do; just apply the formula. If a team asks for 64 addresses, you compute 32 − 26 = 6 and 2⁶ = 64, so you hand them a /26 such as 192.168.5.0/26. One last practical detail: private subnets almost always start with 10.x, 172.x, or 192.168.x, because the other, public ranges are already taken by real websites (for example, 8.8.8.8 belongs to Google's DNS), and reusing them would create a conflict.
Ports — addressing one application on a machine
A port is another simple idea. If an IP address identifies a machine, a port identifies one application on that machine.
A single virtual machine can run many applications at once, so how does an incoming request know which one it is for? Each application is given a unique port — a number, within a fixed range — and the port distinguishes which application a request should go to. To reach an application from the internet you therefore need two things: the machine's IP address (and it must be a public IP if you are coming from the internet; a private IP is reachable only inside the network), and the application's port. You write them together as IP:port — for example, 3.4.5.8:9191 reaches the application listening on port 9191.
Some ports are already taken by well-known applications — MySQL uses 3306 and Jenkins usually starts on 8080 — so when you start your own application you pick a free, unused port such as 9000 or 9191 rather than reusing one that a standard service expects. Knowing which ports to avoid comes with practice.
Before the request — DNS resolution and the TCP handshake
Before your browser sends a single byte of a request to google.com, two things have to happen first. Understanding them is part of understanding the whole journey.
The first is DNS resolution. DNS stands for Domain Naming Service, and the simplest way to think of it is as a database that maps domain names to IP addresses. When you type www.google.com, your router first checks its local cache to see whether it already knows the IP for that name; if it does not, it asks your internet service provider's DNS, which keeps the full records (for example, google.com maps to 8.8.8.8). This step happens first for a good reason: if the name does not resolve to any IP address — say you typed a domain that does not exist — there is no point starting the rest of the journey, especially if you were about to upload a large amount of data.
The second is the TCP handshake. Once the name resolves, your device needs to check that the server is actually willing to accept a request before sending one. This is a three-way handshake: your laptop sends a "hello" (called SYN), the server replies "hello, I'm ready" (called SYN-ACK), and your laptop confirms (called ACK). Three steps, which is why it is called a three-way handshake. (Two-way and four-way handshakes also exist, but the three-way handshake is the common one.)
The OSI model — the journey of data in seven layers
The OSI model is the popular map of what happens to your data as it travels across the internet. It describes the whole journey in seven layers, and once the name has resolved and the handshake is done, this is what actually moves your request.
When you send a request, the data passes down from layer 7 to layer 1; when you receive a response, it passes back up from layer 1 to layer 7. These layers are not physical things — they are a way of explaining, step by step, what happens to the data. Following the request for google.com down the stack:
- Layer 7, Application: your browser initiates the request and decides its type — usually HTTP or HTTPS (it could be FTP). Headers and authentication information are attached here.
- Layer 6, Presentation: the data is encrypted and formatted. This is what HTTPS does, so that even if someone intercepts the data along the way, they cannot read it.
- Layer 5, Session: a session is created between you and the server, so that you are not asked to authenticate again and again — the same reason you stay logged into Facebook across tabs. The session lives in cookies and cache, which is why clearing them logs you out. Layers 7, 6, and 5 are all handled by your browser; the request has not even reached the router yet.
- Layer 4, Transport: the data is segmented into smaller parts (a 10 GB upload cannot go all at once), and the protocol is chosen — TCP or UDP. The choice is standardised: HTTP uses TCP, while something like DNS uses UDP.
- Layer 3, Network: the router adds a source and destination IP address to each segment, at which point the segments are called packets, and the router decides which hops the packets should take to reach the server fastest — like choosing the shortest route from Delhi to Mumbai.
- Layer 2, Data link: because the router is connected to switches, the data is converted from packets into frames, and a MAC address is added so the switch knows the other components on the network.
- Layer 1, Physical: finally the data is turned into electrical signals and sent along the optical cables. From here it travels through many hops across the internet until it reaches the server, where the whole process runs in reverse, from layer 1 back up to layer 7.
Q1What is an IP address?reveal ▸
An IP address is a unique number given to a device that is connected to a network, so that you can identify, track, or control that specific device rather than all of them at once. Using the IPv4 standard, it is written as four numbers separated by dots, such as 192.168.12.4, and you can see your own with ifconfig or ipconfig.
Q2Why can each number in an IPv4 address only go up to 255?reveal ▸
Because a computer stores an IP address as bits, not decimal numbers. An IPv4 address is four bytes, which is 32 bits, and each of the four numbers is one byte, or eight bits. The largest value eight bits can hold is 2⁷ + 2⁶ + … + 2⁰ = 255, so no number in the address can exceed 255 — which is why something like 192.600.12.4 is not a valid IP address.
Q3What is a subnet, and why would you use one?reveal ▸
A subnet is a sub-network — a slice of a bigger network that you carve out deliberately. You use it for security, privacy, and isolation. For example, in an office you might split one network into a secure finance subnet and a free subnet that anyone can join, so that if a hacker compromises a device on the free subnet, they are contained there and cannot reach the sensitive finance systems on the other subnet.
Q4What is the difference between a public and a private subnet?reveal ▸
The only difference is internet access. A public subnet has access to the internet, and a private subnet does not. On a cloud provider you make a subnet public by attaching a route table whose route points to an internet gateway; without that, the subnet stays private.
Q5What is CIDR, and how do you work out how many addresses a range has?reveal ▸
CIDR is how you express the size of a subnet, written as an IP address followed by a slash and a number, such as 172.16.3.0/24. The slash number is how many of the 32 bits are fixed; the rest are free to vary. So the number of addresses is 2 to the power of (32 minus the slash number). A /24 gives 2⁸ = 256 addresses, a /16 gives about 65,000, and a /8 gives about 16 million (these three are class C, B, and A respectively).
Q6A team needs a subnet with 64 addresses. What CIDR do you give them?reveal ▸
A /26. Work it backwards with the formula: you need 2ⁿ = 64, which means n = 6 free bits, and 32 − 6 = 26. So you hand them something like 192.168.5.0/26. The same method covers any size — for 32 addresses it is a /27, and for 8 it is a /29.
Q7What is a port?reveal ▸
If an IP address identifies a machine, a port identifies one application on that machine. A single machine can run many applications, so each gets a unique port number, and the port tells an incoming request which application it is for. To reach an application you need both the machine's IP and the application's port, written as IP:port. You avoid ports already taken by well-known services, such as 3306 for MySQL or 8080 for Jenkins.
Q8What two things happen before a request is even sent?reveal ▸
DNS resolution and the TCP handshake. First, DNS resolution turns the domain name into an IP address; if the name does not resolve, there is no point starting the request. Second, the TCP handshake confirms the server is actually willing to accept a request before your device sends one.
Q9What is DNS resolution, and how does it work?reveal ▸
DNS is the Domain Naming Service, which you can think of as a database that maps domain names to IP addresses. When you request www.google.com, your router first checks its local cache for that mapping; if it is not there, it asks your internet service provider's DNS, which holds the full records (for example, google.com maps to 8.8.8.8). Only if the name resolves does the request continue.
Q10What is the TCP three-way handshake?reveal ▸
It is how your device and the server agree to talk before any data is sent, in three steps: your laptop sends a SYN ("hello"), the server replies with a SYN-ACK ("hello, I'm ready"), and your laptop sends an ACK ("acknowledged"). Because it takes three steps, it is called a three-way handshake.
Q11Explain the OSI model and its seven layers.reveal ▸
The OSI model describes the journey of data across the internet in seven layers; a request goes down from layer 7 to layer 1, and a response comes back up. Layer 7 (Application) — the browser makes the HTTP/HTTPS request. Layer 6 (Presentation) — the data is encrypted and formatted. Layer 5 (Session) — a session is created so you are not re-authenticated. (The browser handles layers 7, 6, and 5.) Layer 4 (Transport) — the data is segmented and TCP or UDP is chosen. Layer 3 (Network) — the router adds source and destination IPs, making packets, and picks the path. Layer 2 (Data link) — MAC addresses are added, making frames, for the switches. Layer 1 (Physical) — the data becomes electrical signals on the cable.
Q12Which OSI layers are handled by the browser?reveal ▸
Layers 7, 6, and 5 — application, presentation, and session. The browser initiates the request, handles the encryption based on the certificate, and maintains the session; the request has not even reached the router while these three layers are being done.
Q13At which layer does data become "packets", and where does it become "frames"?reveal ▸
Data becomes packets at layer 3 (Network), when the router adds the source and destination IP addresses to each segment. It becomes frames at layer 2 (Data link), when the MAC address is added for the switches. The name changes because the medium changes — from the router (packets) to the switches (frames).
Q14What is the difference between the OSI model and the TCP/IP model?reveal ▸
The TCP/IP model is based on the OSI model but combines layers 7, 6, and 5 into a single layer, because those three are all handled by the same component — the browser. Otherwise they describe the same journey. The OSI model is still taught because it is the standard, and if you understand it you understand any model built on top of it.
Networking
16 scenarios · 1–16The complete Networking scenario set, worked through in depth. This is the thinking and the story behind each one, not commands to memorise. Networking is where senior Cloud and DevOps engineers are separated from the pack, because almost every "the app is down" incident is really a networking incident in disguise, and the person who wins is the one who walks the layers methodically instead of guessing.
When "A can't reach B", resist guessing and go up the stack. Each step tells you which layer to stop at, and stopping at the right layer is the whole game:
text1. DNS dig +short B ; dig +trace B # does the name resolve, and to the RIGHT IP?
2. Reach ping B ; traceroute/mtr B # is the host reachable at all? (ICMP may be blocked)
3. Port nc -zv B 443 ; curl -v telnet://B:443 # is the port open / listening?
4. Firewall security group / NACL / host firewall (iptables) # is something dropping it?
5. Listen ss -tlnp (on B) # is the app bound to the right iface:port?
6. TLS openssl s_client -connect B:443 -servername B # does the handshake complete?The mental model: connectivity is a stack of independent things that must all work — name resolution, a route to the host, an open port, no firewall drop, an app actually listening on the right interface, and, for HTTPS, a valid TLS handshake. Any one of them failing breaks the whole thing, and each has its own test. Walking them in order localises the problem in minutes; guessing wastes hours.
The single most useful heuristic — "refused" versus "timed out" (so important that it is also scenario 2):
- Connection refused means you reached the host but nothing is listening on that port (a fast reset), so the app is down or you have the wrong port. Look at the process.
- Connection timed out means your packets vanished into the void, so a firewall, security group, or NACL is silently dropping them, or the route is wrong. Look at the network path.
---
📋 The full scenario inventory (distinct — no padding)
A. Connectivity debugging
- "It works locally but not in prod" (connectivity)
- "Connection refused" vs "connection timed out" (the instant localiser)
- Intermittent connection resets / timeouts under load (SNAT exhaustion)
- MTU / fragmentation mystery (VPN, overlay networks)
B. DNS & TLS
- DNS resolution failure / stale records after a migration
- TLS / SSL certificate errors
C. Load balancing & HTTP
- Load balancer returns 502 / 503 / 504
- HTTP keep-alive / connection pooling issues
- CDN / caching not behaving
D. Firewalls, routing & throughput
- Security Group vs NACL (which is blocking?)
- Firewall / routing asymmetry
- Bandwidth / throughput far below the link speed
E. Cloud & Kubernetes networking
- Designing a VPC / network topology
- IPv4 / pod-IP exhaustion in Kubernetes
- Cross-region / hybrid connectivity design
- DNS-based service discovery failing in Kubernetes (CoreDNS/ndots)
---
1"It works locally but not in prod" (connectivity)Scenario▸
Service A can't reach Service B in prod. It works on a laptop, in staging, or between two other things — but this specific path in this specific environment fails. Vague, and under pressure.
What is actually happening (the mental model).
Something in the path between A and B differs in prod — DNS resolves differently, a firewall or security group blocks it, the app is bound to the wrong interface, or TLS fails. The senior move is to not theorise and instead walk the six layers, letting the first failing one tell you exactly where to stop. "Works locally" almost always means an environmental difference in one of those layers — a firewall that is not there locally, an app bound to 127.0.0.1, or a different DNS view.
How to work through it.
Exactly the reflex above:
dig +short B— does it resolve, and to the IP you expect? (Half of "it's down" is stale or wrong DNS.)ping/traceroute— is it reachable? (ICMP may be blocked, so its absence is not proof of unreachability.)nc -zv B <port>/curl -v— is the port open? Note refused versus timeout, which localises the problem instantly.- The firewall layers — the security group, the NACL, and the host's
iptablesornftables. ss -tlnpon B — is the app bound to0.0.0.0or the right interface, or only to127.0.0.1? Binding to localhost is a classic "works locally, not from another host" cause.openssl s_client— does the TLS handshake complete?
Root causes, and how to tell them apart.
It could be wrong or stale DNS (found with dig), a security group or NACL dropping the traffic (a timeout at step 3), the app bound to localhost (which works locally but is refused or unreachable remotely, as ss shows the bind address), or a TLS failure (found with openssl). Each layer's test isolates one cause.
How to fix it, verify it, and prevent it.
Fix the specific failing layer, and verify end-to-end from the actual source. Prevent "works locally" surprises with environment parity — using infrastructure as code so that the production and staging firewalls and DNS match — and by binding services to the correct interface explicitly.
The trap that less-experienced engineers fall into.
Random pings and service restarts instead of the layered walk — which is both faster and teaches you exactly which layer owns the problem.
🎯 Interviewer follow-up questions you should expect.
- "Walk me through debugging A can't reach B." You go through the six layers in order — DNS, reachability, port, firewall, whether the app is listening, then TLS — stopping at the first failure.
- "It works locally but not from another host — common cause?" The app is bound to
127.0.0.1instead of0.0.0.0—ss -tlnpshows it. - "How does refused vs timeout help?" Refused points to a process or port issue, while a timeout points to a firewall or route dropping the traffic.
nc or curl -v, where refused-versus-timeout localises it, then the firewall layers, then whether the app is even bound to the right interface rather than localhost — binding to 127.0.0.1 is a classic 'works locally, not remotely' cause. Then TLS. Each step tells me which layer to stop at. Structured beats frantic every time in networking."---
2"Connection refused" vs "connection timed out" (the instant localiser)Scenario▸
A connection attempt fails with one of two specific messages — "connection refused" or "connection timed out" — and knowing what each means tells you which half of the problem you're in before you run anything else.
What is actually happening (the mental model).
These two errors come from fundamentally different failures at the TCP level, and that is why they are diagnostic gold:
- Connection refused means your SYN reached the host, but nothing is listening on that port, so the host sent back a RST (reset) immediately. It is fast. It means you got to the machine, but the app is down, has crashed, or is on a different port.
- Connection timed out means your SYN got no response at all; it vanished, and after the retry timeout you give up. It means a firewall, security group, or NACL is silently dropping the packet, the route is wrong, or the host is down or unreachable.
So the error type immediately splits "go look at the process" from "go look at the network path."
How to work through it.
- Read the error precisely — is it refused or timed out?
- Refused means the network path is fine and the problem is at the host: is the app running? On the expected port? Bound to the right interface? Run
ss -tlnpon the host. - Timed out means the app might be fine and the problem is the path: a security group, NACL, or firewall is dropping the packets, the route is wrong, or the host is down. Check the firewall rules and the routing.
The root causes.
For refused, the app has crashed or not started, is on the wrong port, or is bound to a different interface. For timed out, the security group is not allowing the port, the NACL is missing the ephemeral return rule, the host firewall is dropping the packet, the route table is wrong, or the host is genuinely down.
How to fix it, verify it, and prevent it.
Fix the located side and re-test. This heuristic does not need much prevention — it is a diagnostic accelerator that you apply to the other scenarios.
The trap that less-experienced engineers fall into.
Treating both errors as "it's down" and checking everything, instead of letting the error type immediately halve the search space.
🎯 Interviewer follow-up questions you should expect.
- "Connection refused vs timed out — what does each tell you?" Refused means you reached the host but nothing is listening, a process or port issue; timed out means the packets are dropped silently, a firewall or route.
- "You get a timeout to port 443 — where do you look first?" The firewall, security group, NACL, and routing, not the app.
---
3Intermittent connection resets / timeouts under load (SNAT exhaustion)Scenario▸
A service works fine normally but starts throwing intermittent connection resets or timeouts only at peak load — some requests fail, most succeed, and it clears up when traffic drops.
What is actually happening (the mental model).
Peak-only failures point at a resource that only saturates under load. The prime suspects are connection and port limits, and in the cloud the sneaky, senior-signal one is SNAT or ephemeral-port exhaustion on a NAT gateway. When many instances make outbound connections through a NAT gateway to the same destination, they share a limited pool of source ports (about 64,000 per destination IP). Under heavy outbound load to one endpoint, that pool runs out, and new connections get intermittent resets or failures — invisible until you look at the NAT gateway's metrics.
How to work through it.
- Confirm it is load-correlated (it fails at peak and recovers at the trough).
- Check socket state:
ss -s, and the counts ofTIME_WAITandSYN_SENT— pileups hint at churn or exhaustion. - Ephemeral and SNAT ports: are many outbound connections going to a single destination through a NAT gateway? Check the NAT gateway's
ErrorPortAllocationmetric on AWS — a non-zero value means SNAT exhaustion. - A full conntrack table on a stateful firewall or host drops new connections (compare
nf_conntrack_countagainst the max). - Too small a backlog (
net.core.somaxconn) or too low a load-balancer maximum-connection limit under a burst.
Root causes, and how to tell them apart.
It could be SNAT or ephemeral-port exhaustion on a NAT gateway (shown by the ErrorPortAllocation metric and many outbound connections to one endpoint), a full conntrack table (the conntrack count near its maximum), too small a listen backlog, or connection churn from a keep-alive misconfiguration. Each one has a distinct metric.
How to fix it, verify it, and prevent it.
For SNAT exhaustion, distribute the outbound traffic across multiple NAT gateway IPs, use VPC endpoints to keep AWS-service traffic off the NAT entirely (which is often the real fix), or reduce connection churn with keep-alive and pooling. For a full conntrack table, raise the table size or reduce the connection rate. Prevent it by monitoring the NAT gateway and conntrack metrics.
The trap that less-experienced engineers fall into.
Blaming the application for intermittent resets when the app is fine — the NAT gateway is silently exhausting its SNAT ports, which no amount of app debugging reveals.
🎯 Interviewer follow-up questions you should expect.
- "Intermittent resets only at peak — top suspects?" SNAT or ephemeral-port exhaustion on a NAT gateway, a full conntrack table, or too small a backlog.
- "What's SNAT exhaustion?" A NAT gateway has about 64,000 source ports per destination, and many outbound connections to one endpoint exhaust them, causing intermittent failures.
- "How do you fix or avoid it?" VPC endpoints to bypass the NAT, multiple NAT IPs, and connection pooling to reduce the churn.
---
4MTU / fragmentation mystery (VPN, overlay networks)Scenario▸
The unmistakable fingerprint: small requests work, large payloads hang — a health check or small API call succeeds, but a file upload or large response times out or resets. Common right after introducing a VPN, a Kubernetes overlay (VXLAN), or any tunnel.
What is actually happening (the mental model).
Tunnels and overlays add encapsulation headers to every packet, which shrinks the effective MTU below the standard 1500 bytes. Normally, Path MTU Discovery (PMTUD) handles this: a too-big packet triggers an ICMP "fragmentation needed" message telling the sender to use smaller packets. But if a firewall blocks that ICMP (which is very common, because people block "ICMP" wholesale), PMTUD is broken, and large packets silently blackhole — they are dropped with no feedback, so small requests (which fit) work and large ones (which do not) just hang. This is one of the most time-consuming mysteries in networking, and recognising the fingerprint instantly is a huge senior differentiator.
How to work through it.
- Recognise the signature: small requests are fine, but large ones (uploads, big responses) hang or reset — especially over a tunnel, VPN, or overlay.
- Probe the real MTU:
ping -M do -s 1472 <dest>(1472 + 28 header = 1500). If it fails ("message too long" or no reply) but a smaller size works, the path MTU is below 1500. - Fix it: MSS clamping (have TCP negotiate a smaller maximum segment size — the clean fix, often on the tunnel or router), or lower the interface MTU to match the tunnel. Make sure the ICMP that PMTUD needs (type 3, code 4) is not blocked.
The root causes.
Encapsulation overhead (from a VPN or VXLAN) shrinking the effective MTU, combined with blocked ICMP breaking PMTUD, which blackholes large packets. The "small works, big hangs" fingerprint plus a recently added tunnel is the tell.
How to fix it, verify it, and prevent it.
Apply MSS clamping or a matched MTU. Prevent it by configuring the MTU correctly on tunnels and overlays from the start, and by not blanket-blocking ICMP (PMTUD needs it).
The trap that less-experienced engineers fall into.
Debugging the application or the far-end service for days when it is an MTU blackhole — because "it works for small requests" makes it look like an app-level size limit rather than a network-layer packet problem.
🎯 Interviewer follow-up questions you should expect.
- "Small requests work but large ones hang — what is it?" An MTU or PMTU-discovery problem — tunnels add headers, blocked ICMP breaks PMTUD, and large packets blackhole.
- "How do you confirm and fix it?" You run a do-not-fragment ping sweep to find the real MTU, then fix it with MSS clamping or a lower interface MTU, and you don't block PMTUD's ICMP.
---
5DNS resolution failure / stale records after a migrationScenario▸
After a migration or IP change, clients keep hitting the old endpoint — "it works for us but customers still see the old behaviour" — or resolution fails entirely.
What is actually happening (the mental model).
DNS answers are cached at many layers, each with its own TTL — the application, the OS or stub resolver, downstream recursive resolvers, and the CDN. "I updated the record" does not mean clients see it until their cached copy expires. And some clients cache far beyond the TTL — notably the JVM, which by default caches DNS for the life of the process. So a migration's "why are clients still hitting the old IP?" is almost always caching, not a DNS server problem.
How to work through it.
- See the authoritative truth versus what is being served:
dig +trace B(which walks from the root to the authoritative server for the real current answer) versusdig Bagainst your resolver (what is cached). A mismatch means you are seeing a cached answer. - Check the record's TTL and whether it is high (which means slow propagation).
- Rule out local overrides:
/etc/hosts, split-horizon DNS (a different internal versus external view), or negative caching (a cached failure). - Check application caching: long-lived processes, especially the JVM (
networkaddress.cache.ttl), caching a resolved IP indefinitely.
Root causes, and how to tell them apart.
It could be a high TTL that has not yet expired (dig shows the old answer with the TTL counting down), a JVM or app caching forever (the app hits the old IP even after the resolvers updated), a stale /etc/hosts entry, or split-horizon DNS serving a different view. Comparing dig +trace against the resolver's answer distinguishes a server-side problem from a caching one.
How to fix it, verify it, and prevent it.
The key prevention is to lower the TTL a day before a planned migration, so that propagation is fast when you flip, and then raise it back afterwards. For JVM apps, set a sane DNS cache TTL. Verify with dig +trace.
The trap that less-experienced engineers fall into.
Assuming an updated record takes effect immediately and being baffled that clients still hit the old IP — not accounting for TTLs and multi-layer caching, and especially not knowing about the JVM's infinite DNS caching.
🎯 Interviewer follow-up questions you should expect.
- "You updated DNS but clients still hit the old IP — why?" Caching at multiple layers, each per its own TTL — some clients, like the JVM, cache forever.
- "How do you make a migration cutover fast?" You lower the TTL a day ahead so propagation is quick when you flip.
- "dig vs dig +trace?"
digshows the resolver's possibly cached answer, whereas+tracewalks to the authoritative server for the real current answer.
dig +trace shows me the authoritative answer versus what a resolver is serving. Before a planned cutover I lower the TTL a day ahead so propagation is quick when I flip, then raise it back. And I always check for a rogue /etc/hosts entry or app-level caching — JVMs are notorious for caching DNS for the life of the process regardless of TTL."---
6TLS / SSL certificate errorsScenario▸
curl fails with a cert error, browsers warn, or a service-to-service call fails TLS validation. It may work in a browser but fail in curl or Java — a telling detail.
What is actually happening (the mental model).
A TLS error is one of a small, well-defined set, and openssl s_client shows you which in seconds: an expired certificate, an incomplete chain (a missing intermediate certificate), a name mismatch (the SAN or CN does not cover the hostname), the wrong certificate for the SNI, clock skew (the validity window fails on a box with the wrong time), or a protocol or cipher mismatch. The most common real one — and a great senior detail — is the missing intermediate certificate: browsers cache intermediates so it works there, but curl and Java do not, so it fails there.
How to work through it.
openssl s_client -connect host:443 -servername host, and read the presented chain, thenotAfter(expiry), thesubjectand SAN, and theVerify return code.- Diagnose the specific failure:
- a missing intermediate works in browsers (which cache intermediates) but fails in curl and Java, so serve the full chain.
- an expired certificate needs renewal — this should never happen, so it is a process failure.
- a name mismatch means the SAN does not cover the hostname, or the wrong cert is served for the SNI.
- clock skew gives "not yet valid" or "expired" on a box with the wrong time (which ties to the Linux clock-skew scenario).
- Automate renewal (ACM, cert-manager, or Let's Encrypt) with an alert 30 days before expiry.
Root causes, and how to tell them apart.
It could be a missing intermediate (which works in a browser but fails in curl or Java), an expiry (notAfter is in the past), a name mismatch (the SAN versus the hostname), or clock skew (the client's clock is wrong). The "browser is OK, curl fails" split strongly implies a chain problem.
How to fix it, verify it, and prevent it.
Serve the full chain, renew the certificate, or fix the SAN. Prevent it with automated renewal and expiry alerting — a cert-expiry outage is a 100%-preventable unforced error.
The trap that less-experienced engineers fall into.
Only testing in a browser (which caches intermediates and hides a missing-intermediate problem), then being confused when clients and services fail. And letting a certificate simply expire — which should be impossible with automation.
🎯 Interviewer follow-up questions you should expect.
- "Works in a browser but fails in curl — why?" A missing intermediate certificate — browsers cache intermediates, but curl and Java don't, so you need to serve the full chain.
- "How do you debug a TLS error?" You use
openssl s_clientfor the chain, expiry, SAN, and verify code. - "A cert expired in prod — what's the real problem?" A process failure — certificates must auto-renew with an expiry alert.
openssl s_client shows the full chain, expiry, and whether the SNI-selected cert matches the hostname. The most common real cause is a missing intermediate — it works in browsers because they cache intermediates, but fails in curl and Java, so 'works in the browser, fails elsewhere' points me straight at the chain. Second is a plain expiry, which should never happen — certs must auto-renew via ACM or cert-manager with an alert weeks ahead. A cert-expiry outage is an unforced error I'd treat as a process failure, not just renew and move on."---
7Load balancer returns 502 / 503 / 504Scenario▸
Users get 5xx errors from the load balancer. The specific code — 502, 503, or 504 — is the single biggest clue, and treating "5xx" as one undifferentiated thing wastes time.
What is actually happening (the mental model).
Each code points at a different layer, so learning them precisely tells you exactly where to look:
- 502 Bad Gateway means the LB got an invalid or broken response from the backend, or the connection was reset — so the app crashed, returned garbage, or there is an HTTP keep-alive mismatch. Look at the backend process.
- 503 Service Unavailable means there are no healthy targets, or the LB is at capacity — so the health checks are failing and all targets are marked unhealthy, or you have scaled to zero. Look at target health.
- 504 Gateway Timeout means the backend did not respond in time — so the app is slow, or (the classic misconfiguration) the LB idle timeout is shorter than the app's response time. Look at latency and timeout settings.
How to work through it.
- Read the exact code — 502, 503, or 504.
- 502 — check the backend health and logs: did it crash, return an invalid response, or reset the connection? Check for an HTTP keep-alive timeout mismatch (where the backend closes a connection the LB reuses).
- 503 — check the target group health: are the targets passing health checks? Is anything healthy at all? Check the health-check path, port, and thresholds.
- 504 — check the app's response time against the LB idle timeout and any per-target timeout. A slow endpoint, or a timeout shorter than the response time, causes it.
Root causes, and how to tell them apart.
A 502 is an app crash, an invalid response, or a keep-alive mismatch. A 503 is failed health checks, no healthy targets, or a capacity limit. A 504 is a slow backend, or an LB timeout shorter than the app's response. The code itself is the discriminator.
How to fix it, verify it, and prevent it.
Fix the located layer (the app, the health check, or the timeout). Prevent it with proper health checks, aligned timeouts (the LB idle timeout at least the app's response time plus a margin), and connection draining. Alert on 5xx by code, so that next time you know which layer to look at.
The trap that less-experienced engineers fall into.
Treating all 5xx the same and checking everything, instead of letting the code point at the specific layer — especially missing that a 504 is often just an LB idle timeout set shorter than the app's legitimate response time.
🎯 Interviewer follow-up questions you should expect.
- "502 vs 503 vs 504 — what does each mean?" 502 is a bad or invalid backend response, 503 means no healthy targets, and 504 is the backend timing out.
- "You're getting 504s — likely misconfig?" The LB idle timeout is shorter than the app's response time.
- "All requests 503 after a deploy — where do you look?" The target health checks — the new version is failing them, so nothing is healthy.
---
8HTTP keep-alive / connection pooling issuesScenario▸
Latency spikes, intermittent connection resets between services, or high connection churn — often showing up as occasional 502s (tying to scenario 7) or p99 latency that's mysteriously high.
What is actually happening (the mental model).
There are two related failure modes. First, a client keep-alive timeout that is longer than the server's — the server closes an idle connection the client still thinks is open, so the client's next request on that dead connection gets a reset. Second, no connection pooling — every request does a fresh TCP and TLS handshake, which is brutal latency at scale. The senior tuning insight is that the client's idle timeout should be shorter than the server's (and the LB's), so that the client is the one that closes, which avoids the race where it reuses a connection the server has already dropped.
How to work through it.
- Check the symptom: intermittent resets or 502s (a keep-alive mismatch) versus high latency with lots of new connections (no pooling).
- Compare the idle timeouts across the chain — client, LB, server. If the client's is longer than the server's, that is the reset cause.
- Check pooling: is the client reusing connections, or opening a new one (with a TLS handshake) per request? Connection metrics or a tcpdump showing handshakes reveal it.
- Check the pool sizing: is the pool exhausted under load, with requests queuing for a free connection?
Root causes, and how to tell them apart.
It could be a client keep-alive that is longer than the server's (causing resets on reused-but-closed connections), no pooling (a handshake per request adding latency), or a pool that is too small (causing queuing). Comparing the timeouts and the connection metrics distinguishes them.
How to fix it, verify it, and prevent it.
Align the idle timeouts so that client is less than server is less than LB; enable and size the connection pools; and reuse connections to amortise the cost of TLS. Prevent it by setting these consistently across the whole call chain.
The trap that less-experienced engineers fall into.
Ignoring keep-alive alignment and connection pooling — then chasing "random" 502s and p99 latency that are actually connection-churn and timeout-mismatch problems.
🎯 Interviewer follow-up questions you should expect.
- "Intermittent resets between two services — a keep-alive cause?" Yes — if the client's idle timeout is longer than the server's, it reuses a connection the server has already closed.
- "Why does no connection pooling hurt latency?" You pay a TLS handshake per request — pooling amortises it.
- "How should timeouts be ordered?" The client idle timeout should be shorter than the server's, and the LB's, so the client closes first.
---
9CDN / caching not behavingScenario▸
Users see stale content after a deploy, or the CDN isn't caching at all (every request hits the origin, origin load is high, latency poor).
What is actually happening (the mental model).
A CDN caches based on response headers and the cache key. If everything is a MISS, the origin is usually telling it not to cache — through Cache-Control: no-store or private, a Set-Cookie (which disables caching for that response), or a Vary header that fragments the cache key so every request is treated as unique. If content is stale, the TTL is too long or an invalidation was missed on deploy. So you reason about the cache key and the origin's headers together, never the CDN in isolation.
How to work through it.
- Read the headers:
curl -I <url>forCache-Control,Age, and the CDN'sX-Cache(HIT or MISS) and similar. - All MISS means the origin is preventing caching:
Cache-Control: no-storeorprivate, aSet-Cookieon cacheable content, or aVary: *or cookie fragmenting the key so nothing is reused. - Stale content means the TTL is too long, or the deploy did not trigger an invalidation or purge.
- Reason about the cache key: are query strings, cookies, or
Varymaking each request unique?
Root causes, and how to tell them apart.
No caching means the origin is sending no-store, a Set-Cookie, or a Vary that fragments the key (the headers show it, and everything is a MISS). Stale content means a long TTL or a missed invalidation (the Age is high and the content is old). The response headers are the whole story.
How to fix it, verify it, and prevent it.
Fix the origin headers (a cacheable Cache-Control, no Set-Cookie on static assets, and a tighter Vary), and invalidate on deploy. Prevent it with correct cache headers per content type, and automated cache invalidation in the deploy pipeline.
The trap that less-experienced engineers fall into.
Debugging the CDN configuration in isolation when the origin's headers (a stray Set-Cookie or Vary) are what is disabling caching — or forgetting to invalidate on deploy and blaming the CDN for stale content.
🎯 Interviewer follow-up questions you should expect.
- "Everything's a cache MISS — why?" The origin is sending
no-store, aSet-Cookie, or aVarythat fragments the cache key. - "Users see stale content after a deploy — cause?" The TTL is too long, or a cache invalidation was missed.
- "How do you debug it?" You use
curl -Ifor Cache-Control, Age, and the X-Cache HIT/MISS.
X-Cache tells me HIT versus MISS, Age how long it's been cached. If it's all MISS, usually the origin's sending no-store, a Set-Cookie on cacheable content, or a Vary header that fragments the cache key so nothing's reused. Stale content is the opposite — TTL too long or a missed invalidation on deploy. Either way I reason about the cache key and the origin's headers together, not the CDN in isolation, and I make sure the deploy pipeline invalidates the cache."---
10Security Group vs NACL (which is blocking?)Scenario▸
Traffic is blocked in AWS and you need to reason about which control is dropping it — a security group or a network ACL — often after adding a NACL and having "mysterious" breakage.
What is actually happening (the mental model).
The key difference is state:
- A security group is stateful — if you allow inbound 443, the response is automatically allowed back out. It is instance-level and allow-only.
- A NACL is stateless — it evaluates each direction independently, so you must explicitly allow the ephemeral return port range (for example, 1024–65535) for the reply traffic. It is subnet-level, allows and denies, and is evaluated in rule-number order. Forgetting the ephemeral return rule is the number-one NACL mistake.
How to work through it (when something is blocked).
- The security group first — is the port allowed inbound on the destination's security group (and outbound on the source's, if that is restricted)? Since security groups are stateful, that is usually all you need there.
- The NACL, in both directions — is the port allowed inbound, and is the ephemeral return range allowed outbound for the response? This is where being stateless bites you.
- Check the rule order on the NACL (the lowest number wins, so an early deny shadows a later allow).
- Then the host firewall (
iptables).
Root causes, and how to tell them apart.
It could be the security group missing the inbound allow (the simplest case), the NACL missing the ephemeral return range (the classic case — inbound works but responses are dropped), or NACL rule-order shadowing. If the security group is fine but a NACL was recently added and traffic broke, suspect the ephemeral-return rule.
How to fix it, verify it, and prevent it.
Do your real allow-listing at the security-group level (stateful and simpler); use NACLs only for coarse subnet-wide denies, and if you do, remember the ephemeral return rule. Prevent confusion by keeping NACLs minimal.
The trap that less-experienced engineers fall into.
Adding a NACL, allowing the inbound port, and forgetting the ephemeral return range — so requests arrive but responses are dropped, causing a baffling one-way failure.
🎯 Interviewer follow-up questions you should expect.
- "Security group vs NACL — key difference?" A security group is stateful, so return traffic is auto-allowed, while a NACL is stateless, so you must allow the ephemeral return range explicitly.
- "You added a NACL and things broke — likely cause?" You forgot to allow the ephemeral return port range for responses.
- "Where should you do allow-listing?" At the security group, since it's stateful and simpler — use NACLs only for coarse subnet denies.
---
11Firewall / routing asymmetryScenario▸
Traffic mysteriously fails or gets dropped even though both endpoints seem reachable — often with a stateful firewall in the path, or on hosts with multiple NICs or both a VPN and a direct route.
What is actually happening (the mental model).
A stateful firewall must see both directions of a flow — it tracks the outbound connection so that it can allow the matching return traffic. If routing sends the request out one path and the reply comes back a different path, the firewall on the return path never saw the outbound SYN, so it treats the reply as unsolicited and drops it. This "asymmetric routing" breaks stateful devices even when every individual path is technically fine.
How to work through it.
- Suspect it with multi-NIC hosts (two default routes), a VPN plus a direct path, or complex route tables.
- Map both directions:
ip route get <dest>for the outbound path, and check the return path — do they traverse the same stateful device? - If the paths differ and a stateful firewall is involved, that asymmetry is the cause.
The root causes.
A multi-NIC host with two default routes sending replies out the "wrong" interface, a VPN-out but internet-back asymmetry, or misconfigured route tables. The signature is mismatched forward and return paths through a stateful device.
How to fix it, verify it, and prevent it.
Correct the route tables so that the flows are symmetric (both directions traverse the same firewall), use policy routing or source-based routing on multi-NIC hosts, or make the firewall aware of both paths. Prevent it by avoiding accidental multi-path setups and by reviewing the routing whenever you add NICs or VPNs.
The trap that less-experienced engineers fall into.
Not considering routing symmetry — debugging the firewall rules or the app when the actual problem is that the reply takes a different path than the request, so a stateful firewall drops it.
🎯 Interviewer follow-up questions you should expect.
- "A stateful firewall drops traffic even though both ends are reachable — why?" Asymmetric routing — the reply takes a different path, so the firewall never saw the outbound and drops the return.
- "Common cause of asymmetry?" Multi-NIC hosts with two default routes, or a VPN-out-and-internet-back setup.
- "How do you fix it?" You make the routing symmetric, through policy or source routing, or ensure both directions traverse the same firewall.
---
12Bandwidth / throughput far below the link speedScenario▸
A data transfer is far slower than the link should allow — a "10 Gbps" link delivering a fraction of that on a single transfer, especially over distance.
What is actually happening (the mental model).
A single TCP flow's throughput is capped by window size divided by RTT — the bandwidth-delay product — regardless of how fat the pipe is. On a high-latency link, a single connection simply cannot fill the pipe unless the TCP window is large enough. And separately, even tiny packet loss collapses TCP throughput (TCP interprets loss as congestion and backs off hard). So a "slow transfer" is usually latency and loss, not pipe size.
How to work through it.
- Measure honestly: run
iperf3between the endpoints, both a single stream and parallel streams. If the parallel streams are much faster, you were window-limited or single-flow limited. - Check for loss:
mtrorping— even 0.1% loss murders throughput over a high-RTT link. - On a high-latency link, tune the TCP window scaling and use larger buffers, or parallelise across multiple streams to fill the pipe.
- Rule out NIC offload issues and MTU (scenario 4).
Root causes, and how to tell them apart.
It could be the bandwidth-delay-product limit on a single flow (parallel streams fix it, which means it was window-limited), packet loss (mtr shows loss and the throughput collapses), an MTU issue, or NIC configuration. The single-versus-parallel iperf3 comparison and the mtr loss localise it.
How to fix it, verify it, and prevent it.
Tune TCP window scaling, parallelise the transfers, and eliminate the loss. Prevent it by sizing TCP buffers for high-bandwidth-delay-product links and by monitoring for loss.
The trap that less-experienced engineers fall into.
Assuming "slow transfer means a small or congested pipe" and asking for more bandwidth — when the real limit is latency (the bandwidth-delay product on a single flow) or a tiny amount of packet loss, neither of which more bandwidth fixes.
🎯 Interviewer follow-up questions you should expect.
- "A single transfer is slow on a fat link — why?" The bandwidth-delay product — a single TCP flow is capped by window divided by RTT, so you parallelise it or tune the window.
- "Why does a little packet loss hurt so much?" TCP treats loss as congestion and backs off hard, collapsing the throughput.
- "How do you diagnose?" You use
iperf3with single versus parallel streams, andmtrfor loss.
---
13Designing a VPC / network topologyScenario▸
A design question: lay out the network for a new environment or account. This tests whether you think about tiering, blast radius, and — the permanent mistake — CIDR planning.
What is actually happening (the mental model).
Good network design is tiered by exposure, isolates the blast radius, and plans non-overlapping CIDRs so that future peering or VPN stays possible — overlapping CIDRs are an expensive, near-permanent mistake. It uses least privilege by default, and keeps AWS-service traffic private and cheap with endpoints.
How to reason about it.
- Subnet tiers across multiple AZs: public (load balancers only), private (the app tier), and isolated (the data tier, with no route to the internet). Egress from the private tiers goes through NAT, and ingress comes only through the load balancer. No public IPs on the app or data tiers.
- Security groups (stateful, instance-level) for day-to-day allow-listing, and NACLs (stateless, subnet-level) as a coarse backstop only.
- CIDR planning: non-overlapping with other VPCs and on-premises — or peering and VPN become impossible later. Plan generous space for growth.
- VPC endpoints for S3, DynamoDB, and ECR, so that the traffic stays off the internet and the NAT (which is more secure and cheaper, with no NAT data-processing charges).
- Multi-AZ everything for resilience.
The trap that less-experienced engineers fall into.
Putting everything in one flat subnet with public IPs; picking a CIDR that overlaps another VPC or on-premises (permanently blocking future connectivity); and routing S3 and ECR traffic through the NAT gateway instead of a VPC endpoint (which is costly and less secure).
🎯 Interviewer follow-up questions you should expect.
- "How do you tier subnets?" Public for load balancers, private for the app with NAT egress, and isolated for data with no internet — all spread across AZs.
- "Why does CIDR planning matter?" Overlapping CIDRs permanently block peering and VPN, so you plan non-overlapping ranges with room to grow.
- "Security group vs NACL in the design?" Security groups for allow-listing, since they're stateful, and NACLs as a coarse subnet backstop.
- "Why VPC endpoints?" To keep S3 and ECR traffic private and off the NAT — it's more secure, and it avoids the NAT data charges.
---
14IPv4 / pod-IP exhaustion in KubernetesScenario▸
In an EKS cluster, pods fail to schedule with an IP-allocation error, or describe pod shows the CNI unable to assign an address, even though nodes have CPU/memory to spare.
What is actually happening (the mental model).
With the AWS VPC CNI, every pod consumes a real VPC IP address from the subnet (that is how pods get first-class VPC networking). So a busy cluster can exhaust the subnet's CIDR — you run out of IPs before you run out of compute — and pods go Pending with IP-allocation failures. It is a networking constraint masquerading as a scheduling problem, and it surprises people who sized their subnets for nodes, not pods.
How to work through it.
- The symptom: pods are
PendingorContainerCreating, anddescribe podor the CNI (aws-node) logs show no free IPs or an ENI allocation failure. - Confirm subnet exhaustion: compare the free IPs in the pod subnets against the pods scheduled.
- The fixes:
- Prefix delegation — assign /28 prefixes to ENIs so each node can host far more pods per IP allocation (a big density win).
- A secondary CIDR — add more address space to the VPC for the pod subnets.
- Larger pod subnets than intuition suggests, from the start.
- An overlay CNI (such as Calico overlay) to decouple pod IPs from the VPC space entirely — a real architectural trade-off, since you lose native VPC pod addressing.
The root causes.
The subnet CIDR is too small for the pod count under the VPC CNI's one-IP-per-pod model. The IP-allocation error combined with free compute is the tell.
How to fix it, verify it, and prevent it.
Use prefix delegation, a secondary CIDR, or bigger subnets, or an overlay CNI. Prevent it by sizing the pod subnets for the peak pod count (not the node count) up front.
The trap that less-experienced engineers fall into.
Sizing subnets for the number of nodes and being blindsided when the pods exhaust the IPs — not realising that the VPC CNI gives every pod a real VPC IP.
🎯 Interviewer follow-up questions you should expect.
- "Pods won't schedule with an IP error but there's free CPU — why?" The AWS VPC CNI gives every pod a real VPC IP, and the subnet CIDR is exhausted.
- "How do you fix or avoid it?" Prefix delegation, a secondary CIDR, larger pod subnets, or an overlay CNI to decouple pod IPs from the VPC.
---
15Cross-region / hybrid connectivity designScenario▸
A design question: connect on-prem to the cloud, or region to region, or many VPCs together — with the right trade-offs on cost, consistency, and scale.
What is actually happening (the mental model).
There are two key senior insights: weigh cost against consistency for the link type, and know that VPC peering is not transitive — so a growing mesh of VPCs eventually needs a hub, not more point-to-point links.
How to reason about it.
- On-premises to cloud: a site-to-site VPN (cheap, quick to stand up, but rides the public internet with variable latency) versus Direct Connect or ExpressRoute (dedicated, with consistent bandwidth and latency, but costly and with weeks of lead time). Usually Direct Connect with a VPN backup for production.
- VPC to VPC at scale: point-to-point peering does not scale — it is non-transitive (A↔B and B↔C does not give you A↔C) and grows as O(n²). Move to a Transit Gateway hub-and-spoke, which gives transitive routing through a central hub.
- Plan redundancy (dual Direct Connect or VPN), the routing, and — again — non-overlapping CIDRs.
The trap that less-experienced engineers fall into.
Building an ever-growing mesh of VPC peerings (which is non-transitive and becomes unmanageable), or choosing a VPN for a latency-sensitive production workload that really needs Direct Connect's consistency.
🎯 Interviewer follow-up questions you should expect.
- "VPN vs Direct Connect?" A VPN is cheap and quick but rides the internet with variable latency, while Direct Connect is dedicated, consistent, and costly with lead time — usually you'd pick Direct Connect with a VPN backup.
- "Why not just peer all your VPCs?" Peering is non-transitive and O(n²) — you use a Transit Gateway hub instead, which scales.
- "What breaks all of this?" Overlapping CIDRs — you plan them up front.
---
16DNS-based service discovery failing in Kubernetes (CoreDNS/ndots)Scenario▸
Pods can't resolve service names, or external calls from pods are mysteriously slow, or resolution is flaky under load. (This is the Kubernetes DNS scenario, included here because it's fundamentally a networking problem.)
What is actually happening (the mental model).
In-cluster DNS is served by CoreDNS, and pods are configured with options ndots:5 in /etc/resolv.conf. That ndots:5 is the famous trap: for a name with fewer than 5 dots, the cluster search domains are appended and tried first, so resolving an external name like api.stripe.com (2 dots) fires several failed lookups before the real one — adding latency on every external call and hammering CoreDNS, which at scale can CPU-throttle and cause cascading resolution failures.
How to work through it.
- Test from inside a pod:
kubectl exec -it <pod> -- nslookup <service>and an external name — is it internal, external, or both that fail? That split localises it. - Check CoreDNS health:
kubectl get pods -n kube-system -l k8s-app=kube-dns, its logs, and whether it is CPU-throttled under the query volume the ndots amplification creates. - Inspect the pod's
/etc/resolv.conf— thendots:5and the search list; the amplification is why external lookups are slow. - Rule out a NetworkPolicy blocking UDP or TCP 53 to CoreDNS, and confirm the target Service has endpoints.
Root causes, and how to tell them apart.
Slow external lookups mean ndots amplification (and maybe CoreDNS throttling). Total failure means CoreDNS is down or a NetworkPolicy is blocking port 53. An internal-only failure means a Service or endpoints issue. The internal-versus-external split from step 1 points straight at the cause.
How to fix it, verify it, and prevent it.
For the ndots latency, use FQDNs with a trailing dot for external services (which skips the search list), or tune ndots for specific pods. For scale, give CoreDNS adequate resources, autoscale it, and add NodeLocal DNSCache (per-node caching that slashes the CoreDNS load). For blocked port 53, fix the NetworkPolicy to allow DNS egress.
The trap that less-experienced engineers fall into.
Profiling an application for latency that is actually coming from failed DNS lookups on every external call due to ndots — not realising that DNS is the hidden cost.
🎯 Interviewer follow-up questions you should expect.
- "External calls from pods are slow — how could DNS be involved?"
ndots:5appends the search domains first, so external names do several failed lookups before succeeding. - "Nothing resolves at all — what do you check?" CoreDNS health, and whether a NetworkPolicy is blocking port 53.
- "How do you scale cluster DNS?" Adequate CoreDNS resources, autoscaling, and NodeLocal DNSCache.
ndots:5 in the pod resolv.conf — for a name with fewer than five dots it appends the cluster search domains first, so an external name does several failed lookups before the real one. That adds latency on every external call and hammers CoreDNS, which at scale tips it into CPU throttling and cascading failures. I test resolution from a pod for both internal and external names to localise it, use FQDNs with a trailing dot for external services to skip the search list, make sure CoreDNS is properly resourced, and add NodeLocal DNSCache at scale. If nothing resolves, I check CoreDNS health and whether a NetworkPolicy is blocking port 53."---
- Drill the layered reflex first (DNS → reach → port → firewall → listen → TLS) and the refused-versus-timeout heuristic until they are automatic — together they localise most incidents in seconds.
- Break, then fix, in your own lab. Block a port with a security group and watch it time out; stop the app and watch it refuse; serve a certificate without its intermediate and hit it with curl versus a browser; shrink an interface MTU and watch large requests hang; misconfigure a NACL and forget the ephemeral return rule; set a high DNS TTL and watch a "migration" lag. Reproducing the failure teaches ten times more than reading about it.
- One scenario, three passes. Do it in the lab, then say the spoken version without looking, then explain it to a teammate.
- Keep a "symptom → which layer it was" log. Pattern recognition — the MTU fingerprint, refused-versus-timeout, the missing intermediate — is the whole game in networking, and these become the war stories you tell in the behavioural round.