Skip to main content

Dear Friend, You Have Built a Kubernetes: Why HN Keeps Resurfacing This Essay

8 min readDora NodaDora Noda
Share
On this page

In May 2026, a two-year-old blog post hit the front page of Hacker News for the second time. Nobody paid Mac Chaffee to repost "Dear friend, you have built a Kubernetes." Nobody at a Kubernetes vendor seeded the thread. It just kept being true, so a new wave of engineers kept finding it, and the 2026 discussion reran almost the same argument as the 2024 one, line for line.

That recurrence is the actual data point. A marketing claim needs someone paid to repeat it. An observation that resurfaces unprompted, two years apart, on a forum full of people whose job is finding holes in claims — that one's earned its staying power. And the specific claim it keeps earning is a sharper pitch for a Cluster-API-based platform like bex than anything in bex's own feature list, precisely because bex is never mentioned in it.

What the Essay Actually Says, Step by Step

Chaffee's essay is a fake letter to a developer who decided Kubernetes was "overkill" for a simple app. It then narrates, in order, everything that developer builds instead — and the joke is that each step is a smaller, worse version of a Kubernetes primitive that already exists and is already battle-tested.

The build-out goes like this:

  1. A shell deploy scriptdocker build, docker stop, docker run. Works fine for one server, one container.
  2. Docker Compose, once there's more than one service to keep in sync — a supposedly simpler alternative that's really just a config format for the same problem.
  3. An expanded deploy.sh that now handles rolling updates, rollbacks, and manual scaling, because "just restart the container" stopped being an acceptable deploy strategy the first time a bad release took the app down mid-day.
  4. Multi-server infrastructure, once one box can't hold the load — which means parameterizing the deploy script per host and hand-managing firewall rules between them.
  5. A Tailscale overlay network, so the servers can find each other without every service needing to know every other service's public IP — a shell-script scheduler's answer to service discovery.
  6. Ansible, to stop treating servers as pets and start treating them as versioned, reproducible, immutable infrastructure.
  7. A custom Docker API wrapper, so the web app itself can safely ask for a new container to be spawned without shelling out with root access.

Nowhere on that list does the word "health check" appear as its own numbered step — it shows up earlier, folded into step 3, the moment deploy.sh needs to know whether the new container is actually up before it kills the old one. That's not a footnote. It's the same problem Kubernetes solves with kubelet liveness and readiness probes, arrived at independently, solved with a curl loop and a sleep timer instead of a first-class controller.

Chaffee's own punchline names exactly what got built: "a standard config format, a deployment method, an overlay network, service discovery, immutable nodes, and an API server." Every one of those already has a name, a maintainer, and a decade of production hardening. The name is Kubernetes.

This Isn't Just a Satirist's Strawman

It would be easy to read that list as a satirical exaggeration — nobody's deploy.sh really turns into an API server, surely. Except the same convergence keeps showing up in first-person accounts that were never trying to make the essay's point.

A November 2025 postmortem from an engineer explicitly trying to avoid Kubernetes walks through Docker Compose, then Fly.io, then Nomad, looking for something lighter. Each one held up until the app needed exactly the things Kubernetes ships by default: health checks had to be wired up by hand, load balancing needed its own separate piece, secrets needed special-cased handling outside plain environment variables, and autoscaling needed custom logic bolted on top. The author's own summary: "Every 'simpler' DevOps tool is just Kubernetes wearing sunglasses."

One postmortem and one satirical essay aren't a controlled study — this is a pattern worth taking seriously, not a statistically proven law, and both accounts are self-selected (people who hit the wall write about it; people who never outgrow Compose don't). But it's corroborated by the shape of complaint the industry files at scale: the CNCF's 2026 Annual Survey puts Kubernetes production usage at 82% of container users, and roughly a third of existing Kubernetes users still name complexity as a top operating challenge — meaning the convergence the essay describes isn't a one-off joke, it's the default trajectory, and even the people who already made the jump haven't fully escaped the complexity that pulled them there.

The Honest Mapping: What Actually Gets Rebuilt

Here's the essay's own punchline list, lined up against the Kubernetes primitive that already solves each piece — not an analogy, the literal same component:

The essay's homegrown versionThe Kubernetes primitive it re-invents
deploy.sh with rollout/rollback/scaling logicDeployments + ReplicaSets
curl loop before killing the old containerkubelet liveness/readiness probes
Tailscale overlay so services find each otherCNI overlay network
Manually tracking which host runs which serviceServices + CoreDNS (service discovery)
Ansible treating VMs as versioned, reproducible hostsDeclarative Node objects, immutable by replacement
Custom Docker API wrapper for the app to request containerskube-apiserver + the scheduler

Every row on the right side is a component that already exists, is already maintained by a community bigger than any one team, and has already absorbed a decade of edge cases the left column hasn't hit yet. That's the entire argument in one table: the homegrown version isn't simpler, it's just newer, which means it's failed less — so far.

The Half of This Argument bex Already Agrees With

This is where it gets uncomfortable to be honest about, and worth being honest about anyway: bex does not make this table disappear. Cluster API and Cluster API Provider Hetzner — the actual machinery underneath bex — are the right-hand column. That complexity is real, it exists, and somebody has to run the reconciliation loops, patch the control plane, and handle the version skew. bex's answer to the essay isn't "you don't need any of this." It's "you don't need to be the one holding it, and you don't interact with it through kubectl and YAML — you interact with it through git push."

That's a real, and important, concession to the essay's other side. This argument does not mean every team needs Kubernetes today. A single-service app running comfortably on one box, with no second server in its near-term future, will never hit the convergence point the essay describes — for that team, a deploy.sh that never grows past step 1 is the correct amount of infrastructure, not a mistake waiting to happen. The essay's critics on that same 2026 HN thread made a fair point back: adopting Kubernetes "just in case" is its own kind of overengineering, and plenty of teams pretending to be Google when they aren't is a real failure mode too.

What the essay's argument actually targets is narrower and sharper than "always use Kubernetes": it's the team that's already past that point — already juggling more than one server, already writing a health-check loop, already hand-rolling service discovery — and still telling itself the homegrown version is the simple choice. For that team, "simple" was never on the table. The only open question was whether the complexity they'd already accumulated would be documented, maintained, and battle-tested, or invisible, load-bearing, and understood by exactly one engineer who might leave.

Why an Essay That Never Mentions bex Is a Better Pitch Than bex's Own Feature List

A feature list is a comparison of what two products do today. It's easy to argue with, because today's checkbox gaps are visible, countable, and sometimes just wrong — the same 2026 HN thread had commenters pointing out, correctly, that Kubernetes doesn't actually hand you deployments, networking, or certificates fully solved either; you still have to pick and configure Helm charts, Ingress controllers, cert-manager. Kubernetes' own feature list has real gaps too.

The essay doesn't compete on that axis at all. It competes on a cost the reader hasn't priced in yet: the 18-months-from-now version of their own shell scripts, the day a teammate who understood the Tailscale routing rules leaves, the incident where the custom Docker API wrapper has a bug nobody's looked at since the person who wrote it moved teams. Nobody on that HN thread — not the people defending Kubernetes's ecosystem value, not the people mocking its YAML sprawl — disputed the core convergence claim itself. They argued about when it applies and how much it costs to get ahead of, not whether it happens.

That's a sturdier argument than any roadmap slide, because it isn't asking the reader to trust bex's claims about bex. It's asking them to trust their own two-years-from-now team, which is a harder thing to argue yourself out of.


bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on Cluster API-managed machines you own, with the reconciliation loop already handled instead of hand-rolled. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex