Project challenges / verified progress
Beacon: build an SSL and uptime monitor in Go

The engineering notebook

Resolve the name first

What really happens before a program can connect to a hostname?

Loading statusStage 2 of 10

  • Workspace not ready
  • Agent not ready
Focus25:00
A small focus ritual

0 focus sessions completed. Every fourth session offers a longer break. Start each phase when you are ready.

Study time never unlocks verified lesson progress.

Loading...

Loading verified progress...

Loading GitHub account...
Phase 1 — One check, one answer

Step 01 of 06

Learn the concept

In 2021, a major Slack outage began with DNS trouble, not an app server fire. If a name does not resolve, your beautiful TLS, HTTP and retry logic never get a turn. DNS is the front door, and it has its own locks.

NAME TO ADDRESSES01Stub resolverlocal rules and cacheon this host02Rootwho handles .com?delegation03TLDwho owns example.com?more delegation04Authoritativereturns A and AAAAreal answer
The process may end on the local machine if `/etc/hosts` or a cache answers. When it leaves, the recursive resolver follows delegated authority until it reaches a server allowed to answer for the zone. That path is why two regions can see different DNS facts at the same time.
Step 01

The ideas this is made of

The stub resolver is the process's first witness

Your Go program usually asks the operating system resolver, not the root servers. That stub can consult /etc/hosts, search domains, /etc/resolv.conf and local policy before any public DNS packet exists. Containers, laptops and servers can therefore resolve the same name differently. Treat the local resolver path as part of the measurement, not as invisible plumbing.

Recursive DNS is delegated authority, not a database lookup

A cold recursive resolver starts high in the tree. Root servers point it at .com; .com points it at example.com; the authoritative server returns the address records. No one server knows everything. That design lets ownership scale, but it also means latency and failure can happen before the destination service ever sees a packet.

A, AAAA and CNAME records answer different questions

An A record gives an IPv4 address. An AAAA record gives an IPv6 address. A CNAME says, ask under this other name instead, and the resolver must chase the chain. Modern clients often ask for both A and AAAA, then choose an address family. The result is a set of candidates, not a promise that every candidate is reachable from this network.

TTL trades freshness for speed

Every DNS answer carries a time to live. A 300 second TTL says caches may reuse it for five minutes. That is why second lookups are often fast. It is also why a bad address, or even NXDOMAIN, can outlive the fix. Low TTLs help failover. High TTLs reduce query load. Neither is free.

Go's resolver path can change under your feet

Go can use its pure-Go resolver or the system resolver through cgo. The system path may honour enterprise NSS plugins, mDNS or LDAP; the pure-Go path is portable and scheduler-friendly. Do not build diagnosis on guesses about which one ran. Use net.Resolver.LookupIPAddr(ctx, host), measure it, and record the error it returns.

Resolve a name without opening a connection
package main

import (
	"context"
	"fmt"
	"net"
	"time"
)

func main() {
	resolver := net.Resolver{}
	start := time.Now()

	addrs, err := resolver.LookupIPAddr(context.Background(), "example.com")
	elapsed := time.Since(start)
	if err != nil {
		fmt.Println("dns failed:", err)
		return
	}

	fmt.Println("resolved in:", elapsed)
	for _, addr := range addrs {
		fmt.Println(addr.IP.String())
	}
}

This asks only the naming question. No port is dialled. No HTTP request is sent. If it is slow or empty, the fault is already narrowed to the resolver path in front of this process.

Records people merge by accident

RecordAnswersOperational clue

A

IPv4 address

Can connect over IPv4

AAAA

IPv6 address

Can connect over IPv6

CNAME

Another DNS name

Follow the alias chain

NXDOMAIN

No such name

May be cached too

What these are called on the job

  • Stub resolver — The resolver applications call first. It applies local rules and usually forwards questions.

  • Recursive resolver — The resolver that follows delegation and caches answers for clients.

  • Authoritative server — A DNS server allowed to answer for a zone such as example.com.

  • TTL — Time to live: how long a DNS answer may be cached.

  • NXDOMAIN — The DNS response code for a name that does not exist.