Core CS · Computer Networks
Four questions, and only the last one answers
A packet header has nowhere to write a name. No single machine holds the mapping either, so every lookup walks a tree from the root downward, one refusal at a time, and then caches the result so it never has to happen again.
Resolve one name down the tree, then watch the cache answer it in one step →01 The idea
People use names, packets carry addresses
Every connection you make starts with a number. The destination address field in an IPv4 header is 32 bits wide and in IPv6 it is 128 bits, and there is nowhere in either header to write the college website. A router forwards on addresses and nothing else. So before a single packet leaves your machine, something has to turn the name you typed into an address, and that lookup is a network operation in its own right: it has its own protocol, its own port, its own failure modes, and its own latency that you pay before the real connection even begins.
The first version of the solution was one file. On the early ARPANET a single HOSTS.TXT listing every host and its address was maintained centrally at the Network Information Center at SRI, and every machine on the network fetched a fresh copy periodically. It worked while there were a few hundred hosts, and it failed for three reasons that any central registry eventually hits. The file itself grew without bound. The load on the one machine serving it grew roughly with the square of the network size, because both the number of entries and the number of machines fetching them were increasing at once. And a single registry means one organisation approving every name on earth, which is an administrative bottleneck long before it is a technical one.
What replaced it, in 1983, is the Domain Name System, and it fixed all three problems with the same move: split the database up and hand each piece to whoever actually owns it. Three properties follow, and they are the three things to hold on to. The name space is a tree. Authority over the tree is delegated downward, so the people who run examate.in answer for the names inside it and nobody has to ask permission to add one. And every answer carries a TTL, a lifetime, so it can be cached by anyone who sees it.
Read a name the way the tree is built, which is right to left. In www.examate.in. the trailing dot is the root, an empty label that is almost always left off when you type but is always there on the wire. To its left, in is the top level domain. Then examate.in is the second level domain, the piece an organisation registers. Then www is a subdomain or host name inside it. Each dot-separated piece is a label, capped at 63 bytes, and the whole encoded name is capped at 255 bytes. Written out in full with the trailing dot, ending at the root, the name is a fully qualified domain name, and it is unambiguous. Written without it, www on its own means whatever your machine's search list decides it means.
Everything else in this lesson follows from one uncomfortable fact: no server holds the whole map. There is no machine you can ask that knows where www.examate.in is and also where every other name on the internet is. The root servers know only which servers were delegated each top level domain. The .in servers know only which servers were delegated each domain inside .in. Only the last server in the chain has the actual address, and finding it means walking down the tree collecting one refusal per level.
02 Worked example
One name, resolved from a completely cold cache
One name, worked end to end, and it is the same name for the rest of the lesson: www.examate.in., record type A. Nothing anywhere is cached. The root server address 198.41.0.4 is the real one for a.root-servers.net; every other address here comes from the documentation ranges reserved by RFC 5737, so none of them can collide with a real host. Read left to right.
Four queries for one name, and three of them were sent by a machine you never spoke to. Count what each participant actually did, because the counting is the answer to half the questions asked about this topic. The stub asked once, and its query was recursive: it set RD=1, which means do not send me a referral, go and get the finished answer. A stub never sees a referral in its life. The resolver asked three times, and its queries were iterative: RD clear, take an answer or a pointer, whichever you have. Notice that all three carried the identical question, www.examate.in. A. The resolver does not ask the root about in and then the TLD about examate; a DNS query always carries the complete name, and it is the server that decides how much of it it can act on.
Now the highlighted node, because why the root refuses to answer is the follow-up. It is not being unhelpful and it is not overloaded. The root zone physically contains delegations and nothing else: on the order of 1,500 top level domains, each with a handful of NS records. There is no entry in it for www.examate.in and there never will be, because storing one would mean storing every name on the internet in one zone, which is the exact design that HOSTS.TXT died of. The same argument repeats one level down: the .in registry stores which nameservers were delegated each registered domain, not what is inside those domains, which is why you can add a hostname to your own zone this afternoon without telling a registry anything.
Two details in that reply carry marks. The Authority section holds NS records, and an NS record holds a name, not an address. So a referral to ns1.examate.in. would be circular on its own: to reach the server for examate.in you would have to resolve a name that is itself inside examate.in. That is what the Additional section is for. The parent zone publishes glue, the A record for the nameserver, alongside the delegation, and the circularity is broken. Second, the resolver never had to ask anybody where the root servers are. It ships with a root hints file listing all thirteen of them by name and address, and that file is the one piece of hardcoded knowledge in the entire system. Everything else is discovered.
While we are on the thirteen: there are 13 named root server identities, a.root-servers.net through m.root-servers.net, and that number was chosen because thirteen name-and-address pairs were the most that would fit in the original 512-byte UDP DNS reply. The honest real-world clause, and it is worth saying out loud in an interview because it shows you know why the number is stale: those are 13 addresses, not 13 machines. Each one is announced from many locations at once using anycast, where the same IP address is advertised into BGP from hundreds of sites and the routing system delivers your packet to the nearest one, so the real count is well over a thousand physical servers on every continent.
Finally, the number that decides whether any of this ever happens again: the 300 in www.examate.in. 300 IN A 203.0.113.25. That is the TTL in seconds. For the next 300 seconds, any query to that resolver for that name is answered out of memory in one step with no walk at all, and the resolver returns the remaining lifetime rather than the published one. Run the same lookup twice in a row and watch the TTL go down; that is how you tell a cached answer from a fresh one without any other tooling. Caching happens at every level, not only at the resolver: the stub caches if it caches at all, the resolver caches, and the resolver also caches the two referrals it collected, so the next lookup of any name under examate.in starts from the delegation rather than from the root. And the negative case is cached too. If the authoritative server had replied NXDOMAIN, this name does not exist, RFC 2308 says that non-existence is itself cached, for a lifetime taken from the zone's SOA record, so a typo in a link does not re-walk the tree on every retry.
03 Mechanics
The five roles, the two words, and the records
Four tables, in the order the questions come. First the participants, because almost every wrong answer about DNS comes from collapsing two of these five into one. Read the last column as a promise: it is what that box will and will not put in a reply.
| Role | Where it runs | What it holds | What it replies with |
|---|---|---|---|
| Stub resolver | Inside your OS, reached through getaddrinfo() | A tiny cache, and the resolver's address from /etc/resolv.conf or DHCP option 6 | Nothing. It asks one question and waits. |
| Recursive resolver | Your ISP, your home router, or a public service | A large shared cache and the root hints file | The finished answer, or a failure such as SERVFAIL or NXDOMAIN |
| Root server | 13 anycast identities, a to m.root-servers.net | The root zone: a delegation for every TLD | a referral to the TLD, never an answer |
| TLD server | Run by the registry for that TLD | A delegation for every domain registered under it | a referral to the domain’s nameservers |
| Authoritative server | Run by the domain owner or their DNS provider | The zone file itself, the actual records | The answer, with AA set. Or NXDOMAIN, also authoritatively. |
The row people merge. The stub and the recursive resolver are not the same thing and they do not do the same job. The stub is a library, not a server, and it walks nothing. The resolver is the only box in the list that ever moves down the tree, and it is also the only one whose address you configure. If you remember one sentence from this table, make it that one: the recursion happens at the resolver, and the iteration happens beneath it.
Which is the second table, and the one worth being pedantic about. Recursive and iterative are not two kinds of DNS. They are two legs of the same lookup, and the words describe who does the walking.
| Recursive query | Iterative query | |
|---|---|---|
| The asker is saying | Go and get me the final answer for this name. | Give me the answer if you have it, otherwise tell me who to ask next. |
| The RD bit | RD = 1 | RD = 0 |
| If the server cannot answer | It goes and asks other servers on your behalf | It returns a referral and stops. Its job is done. |
| Who does the work | The server | The asker |
| Used on which leg | Stub to recursive resolver | Recursive resolver to root, TLD, authoritative |
| What comes back | One answer, or one failure | A referral at every hop but the last |
| Number of queries in section 02 | 1 | 3 |
The sentence that gets the mark. The client's query is recursive; the resolver's queries are iterative. Answering "DNS is recursive" or "DNS is iterative" without naming the leg is the single most common way this question is failed, because both halves are true of different halves of the same lookup. Two clauses worth adding. An authoritative server asked with RD=1 does not perform recursion for you; it ignores the bit, answers if the name is in its zone, and otherwise refers or refuses. And a recursive resolver that will do this work for anybody on the internet is called an open resolver, which is how DNS amplification attacks are built: a small forged query produces a large reply aimed at the victim whose address was spoofed.
Third, the records. A zone is a set of resource records, each written as name, TTL, class, type, then the data. The class is IN for internet and you will realistically never see another. What matters is the type, and specifically what each type is allowed to hold.
| Type | What it holds | Example | The trap |
|---|---|---|---|
| A | One IPv4 address, 32 bits, four bytes of data | www.examate.in. 300 IN A 203.0.113.25 | The type is A for address, not "IP". One record holds exactly one address; several A records for one name is how simple load spreading is done. |
| AAAA | One IPv6 address, 128 bits | www.examate.in. 300 IN AAAA 2001:db8:42::25 | Four times the bits of an A record, which is where the four As come from. A host can publish both and the client chooses. |
| CNAME | another NAME, never an address | shop.examate.in. 3600 IN CNAME cdn.example.net. | A CNAME cannot point at an address, cannot sit at the zone apex, and cannot coexist with any other record at the same name. Resolving it means starting a fresh lookup on the target. |
| MX | A 16-bit preference plus a mail exchanger's name | examate.in. 3600 IN MX 10 mail1.examate.in. | the LOWER preference is tried first — and the target must be a name that has an A or AAAA record, never a CNAME and never an address literal |
| NS | The name of a server delegated to answer for a zone | examate.in. 172800 IN NS ns1.examate.in. | It appears twice: in the parent zone as the delegation, and inside the child zone itself. The parent's copy is the one a resolver follows on the way down, and only the child's copy is authoritative. |
| PTR | A name, for the reverse lookup address to name | 25.113.0.203.in-addr.arpa. IN PTR www.examate.in. | The address is written backwards and lives under in-addr.arpa, or ip6.arpa for IPv6. A PTR is not created automatically and is not required to agree with the A record. |
| TXT | Arbitrary text strings | examate.in. 3600 IN TXT "v=spf1 mx -all" | This is where SPF, DKIM and domain-ownership proofs live. DNS does not interpret any of it; the mail server or the verifying service does. |
| SOA | Zone metadata: primary server, admin mailbox, serial, refresh, retry, expire, minimum | examate.in. IN SOA ns1.examate.in. hostmaster.examate.in. 2026080601 7200 3600 1209600 300 | Exactly one per zone. Its minimum field is no longer a default TTL: RFC 2308 redefined it as the negative caching lifetime, the one at the end of that line. |
Why a CNAME cannot sit at the apex, which is asked more often than it looks. The apex of a zone, the bare examate.in., must carry an SOA record and its NS records. A CNAME is not allowed to coexist with any other record at the same name, because a CNAME means this name is an alias, look at the other name instead, and that is incompatible with also having data of your own. So examate.in. CNAME something is illegal, which is exactly why you cannot point a bare domain at a CDN hostname the obvious way. Providers solved it with non-standard records that behave like a CNAME to the outside world but return A records: Route 53 calls them alias records, Cloudflare calls it CNAME flattening. Naming that workaround is a strong answer, because it shows you know it is a workaround.
Last, the transport and the message, because "why does DNS use UDP" is a guaranteed question and the good answer has arithmetic in it.
| Question | Answer | Why it is that way |
|---|---|---|
| Port | 53, on both UDP and TCP | The same port number is registered for both transports. TCP is not a different service. |
| Default transport | UDP | A query and its reply are one small datagram each. No handshake means one round trip instead of two, and a lost query costs one retransmission rather than a connection. |
| When TCP is used | truncated replies, and zone transfers | If the reply will not fit, the server sends what it can with the TC (truncated) bit set and the client repeats the query over TCP. Zone transfers move a whole zone and need reliability and ordering. |
| Original UDP size cap | 512 bytes of DNS payload | RFC 1035. This is also the reason there are exactly 13 root servers. |
| Getting past 512 | EDNS(0), RFC 6891 | The client advertises a larger UDP buffer in an OPT pseudo-record, commonly 1232 bytes since the 2020 recommendation, or 4096 on older software. |
| Header | a fixed 12 bytes | A 16-bit ID, 16 bits of flags including QR RD RA AA TC and the 4-bit RCODE, then four 16-bit counts, one per section. |
| The four sections | Question, Answer, Authority, Additional | A referral is exactly the reply where Answer is empty and the other two are full. |
| Zone transfers | AXFR full, IXFR incremental | How a secondary authoritative server copies the zone from the primary. Both run over TCP. |
| Common RCODEs | 0 NOERROR · 2 SERVFAIL · 3 NXDOMAIN · 5 REFUSED | NXDOMAIN means the name does not exist. SERVFAIL means the resolver could not find out, which is a very different problem. |
| Encrypted variants | DoT on TCP 853 · DoH on TCP 443 | Plain DNS on port 53 is neither encrypted nor authenticated. DNSSEC signs records so you can detect forgery, but it does not hide anything; DoT and DoH hide the traffic but do not authenticate the data. |
The arithmetic behind "why UDP", and it is worth being able to produce. Take the query from section 02. The header is 12 bytes. The question section holds the encoded name plus a 2-byte type and a 2-byte class, and a name is encoded as a length byte in front of each label with a zero byte for the root: 3www is 4 bytes, 7examate is 8, 2in is 3, and the root label is 1, so the name is 16 bytes and the question section is 20. The whole query is 32 bytes. Opening a TCP connection to carry 32 bytes costs a full round trip before the question is even asked, plus connection state on a server answering millions of these. If a UDP query is lost the resolver asks again after a second or two, which is cheaper than any handshake and is why the retry, not reliability, is the right tool here.
Why this is the outage that takes everything with it. Every protocol in this course begins with a DNS lookup, so when name resolution fails nothing works, and it does not look like a DNS problem. It looks like every service being down at once. The failure is also strangely delayed, because while records are still cached the outage is invisible, and it becomes total only as those TTLs run out. In October 2016 a large DDoS against Dyn's authoritative infrastructure made a long list of perfectly healthy sites unreachable for hours, purely because their names could not be resolved. The defence is the same one you would apply to any single point of failure: publish your zone on two independent authoritative providers, on separate NS records, so losing one is survivable.
And the honest part, which is about the TTL you chose months earlier. A long TTL is free until the day you need to change something. Recovery from a bad record is not instant, because a record you published with an 86400-second TTL is held by caches you do not control and cannot flush for up to 24 hours after you fix it. There is no push, no invalidation and no "propagation" to wait for; there is only expiry. That is why a planned migration starts by lowering the TTL before the change rather than during it, and why one bad TTL decision is what turns a five-minute outage into a day-long one.
05 Cheat sheet
The answers that get asked, and the wrong ones that get given
Every row is something you can be asked to state in under ten seconds. The right-hand column is the specific wrong answer that gets written down, not a general caution.
| What they ask | The answer | The trap |
|---|---|---|
| Port and transport | 53, UDP by default, TCP on the same port when needed | "DNS is UDP" — TCP is specified, not a workaround |
| What forces TCP | a reply with the TC bit set, and every zone transfer | Saying "large replies" without naming the TC bit or AXFR. |
| Recursive vs iterative | the stub’s query is recursive, the resolver’s queries are iterative | "DNS is iterative" — true of one leg only; name the leg |
| Who can answer www.examate.in | only the authoritative server for examate.in | Saying the root, or the TLD. Neither has ever heard of the name. |
| What the root returns | a referral: Answer empty, NS in Authority, glue in Additional | Calling it an error. A referral is a successful reply with RCODE 0. |
| Why glue exists | the NS name is inside the zone being delegated | Forgetting that an NS record holds a name, so a delegation alone would be circular. |
| How many root servers | 13 named identities, a to m.root-servers.net, anycast to 1000+ machines | "13 computers" — and the 13 comes from the 512-byte UDP limit |
| What a CNAME may point at | another name, and nothing else | a CNAME to an IP address — and never at the zone apex |
| MX preference | the lower number is tried first | Assuming higher wins, and pointing an MX at a CNAME. |
| What a TTL controls | how long any cache may keep this record, in seconds | Thinking the server pushes updates. Nothing is pushed; records only expire. |
| Negative caching | NXDOMAIN is cached too, for the SOA minimum field (RFC 2308) | Thinking only successes are cached, so a typo re-walks the tree every time. |
| Name and label limits | label 63 bytes, whole encoded name 255 bytes | Quoting characters rather than bytes, and forgetting the length byte per label. |
| Header, sections, and the secure ports | 12-byte header · Question, Answer, Authority, Additional · DoT 853, DoH 443 | "DNSSEC encrypts DNS" — it signs; DoT and DoH encrypt |
06 Where & why
Four systems you can point at, and what each of them changes
None of this is a teaching abstraction. Each of these is a box in section 03's table, run by somebody real, and each one differs from the textbook in a way worth naming out loud.
Setting your machine's resolver to 8.8.8.8, or 8.8.4.4, or 2001:4860:4860::8888, replaces one box in the chain and nothing else: it still does the same iterative walk from the root that your ISP's resolver would have done. What you gain is a very large shared cache, so most names are already warm. What you give up is locality. Content delivery networks answer with an address near the resolver, so a distant resolver can hand you a distant server, which is what EDNS Client Subnet exists to fix by passing a truncated version of your address along with the query.
dig www.examate.in A shows the answer and its TTL; run it twice and watch the TTL fall, which proves the second reply came from a cache. dig +trace turns off recursion and performs the iterative walk itself, printing the root's referral, then the TLD's, then the authoritative answer, in exactly the order of this lesson. dig +norecurse sets RD=0 on a single query, which is how you ask a resolver "do you already have this cached" without making it go and find out.
Named after the port. It runs the authoritative servers for a zone, so it is the last box in the chain rather than the resolver. It is also where the apex restriction from section 03 becomes a product decision: because a CNAME cannot sit at examate.in, Route 53 offers alias records, which look like a CNAME in the console but return real A records at query time. Health checks with DNS failover are the other common use, and they inherit the TTL problem exactly: a failover is only as fast as the TTL on the record being swapped.
Every pod's /etc/resolv.conf points at the cluster's DNS service, and a service name such as payments.default.svc.cluster.local resolves to its ClusterIP through an ordinary A record. The famous trap is the generated ndots:5 option: any name with fewer than five dots is tried against every search domain first, so a lookup of an external name like api.stripe.com costs three failed lookups against the cluster search domains before the real one, doubled again if the stub asks for A and AAAA. It is a pure DNS problem, it shows up as latency in the application, and the fix is a fully qualified name with the trailing dot.
07 Interview questions
What they ask, and what they follow up with
"What happens when you type a URL into a browser" is the most asked open-ended question in this syllabus, and the DNS part is where most answers go vague. Say the roles out loud in order, and say which query is recursive and which are iterative; an answer with no referrals in it reads as memorised.
Walk me through what happens between typing a name and the first packet leaving your machine.
Is DNS recursive or iterative?
Why does the root server not just answer the query? Is a referral an error?
An NS record holds a name, not an address. So how does the resolver ever reach that server?
Why are there exactly thirteen root servers?
Why does DNS use UDP, and what forces it onto TCP?
What does a TTL actually control, and who counts it down?
What is the difference between NXDOMAIN and SERVFAIL?
What is inside an MX record, and which mail server is tried first?
What does a reverse lookup actually query, and can I trust the result?
Is DNS secure? What do DNSSEC, DoT and DoH each give you?
People call DNS a single point of failure. What actually breaks, and what do you do about it?
08 Practice problems
Six to work on paper
Draw the chain of participants before you answer any of these, and mark on it which link is recursive and which are iterative. Three of the six turn on a TTL rather than on a query, and two of them cannot be answered without adding up bytes.