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

The engineering notebook

One request, one answer

What does it actually mean to say a website is up?

Loading statusStage 1 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

A monitoring company is a few hundred engineers and a billion-dollar valuation built on one four-line function: ask a server a question, write down the answer. Everything else — dashboards, alerts, certificate warnings, status pages — is scaffolding around that single act. You are about to write the four lines.

ONE CHECK, TWO WAYS TO ENDhttp.Get(target)one question, asked onceNo answer at allDNS, refusal or deadlineerr != nilAn answer you likethe server handled it and said so2xxAn answer you don'ttransaction fine, service not4xx / 5xx
The top branch is a network fault and the bottom two are server verdicts. Beginner monitors collapse all three into "it responded, so it's fine" — which is exactly why they report a site serving 500s as healthy. Keep the branches apart from the first line of code and they stay apart for the rest of the course.
Step 01

The ideas this is made of

A check is a question, not a state

"Is the site up?" has no answer. The answerable version is: did this URL respond successfully when I asked it, just now, from here? A site can be up from your laptop and down from Frankfurt. Up at 10:00, down at 10:01. Beacon never claims a site is up — it records that a check succeeded, at a time, from a place.

The status code is the server's own verdict

Every HTTP response opens with three digits the server chose about itself. 2xx: I handled it. 3xx: it lives elsewhere. 4xx: your request was wrong. 5xx: I broke. Bytes coming back is not success — reading the code is the minimum honest check.

Go splits the two failures for you, if you let it

resp, err := http.Get(url) returns both. A non-nil err means no HTTP transaction ever happened and resp is nil — touching it panics. A nil err means the transaction completed perfectly, even if it carried a 503. Conflating them is the classic beginner bug, and it hides which layer actually broke.

The body is an open connection, not a string

Go hands you the response before the body has been read, and that body is a live socket. Never close it and the connection is never released. Do that in a loop and the process climbs towards its file-descriptor limit until the OS refuses to open any more. defer resp.Body.Close() goes immediately after the error check — build the reflex now, while the program is four lines long.

The smallest honest check there is
package main

import (
	"fmt"
	"net/http"
)

func main() {
	resp, err := http.Get("https://example.com")
	if err != nil {
		// Branch one: no transaction happened. resp is nil — do not touch it.
		fmt.Println("unreachable:", err)
		return
	}
	defer resp.Body.Close()

	// Branches two and three: the transaction worked. Now read the verdict.
	fmt.Println("status:", resp.StatusCode)
}

Nine lines holding all three branches, the closed body, and a status code read rather than assumed. Type it out — don't paste it — and run it. Then break it deliberately: point it at https://not-a-real-host.invalid and watch the other branch run. A failure path you have never executed is a failure path you do not have.

The two failures, side by side

No answer arrivedA bad answer arrived

What happened

The request never completed

The request completed fine

In Go

err != nil, resp is nil

err == nil, read resp.StatusCode

Typical cause

DNS, routing, refusal, timeout

Bad deploy, dependency down, bad path

Who you'd wake up

Network or platform

Whoever owns the service

Beacon records it as

A transport error, named by layer

A reachable endpoint, unhealthy

What these are called on the job

  • Probe — One execution of a check against one target. Beacon's unit of work — and the same word Kubernetes uses for its liveness and readiness checks, which you will meet again in course four.

  • Target — The thing being watched: a URL, or a host and port. One constant today, a configured list by course two.

  • Transport error — A failure that happened before any HTTP response existed. In Go, the non-nil error from the client.

  • Status code — The server's own three-digit verdict on the request it just handled.