Journal — October 9, 2025 · 5 min read
Kubernetes When You Don't Need Kubernetes
Deployment options form a ladder, and most teams climb two rungs past the one their workload justifies. The real cost of a cluster, and the conditions where Kubernetes actually earns it.
Most teams running Kubernetes are standing two rungs higher on the deployment ladder than their workload justifies. I know, because I put a product on Kubernetes that had no business being there and spent a quarter paying for it in attention.
Every deployment option sits on a ladder. Each rung buys something real and charges you in operational time. The failure isn't picking the wrong tool, it's climbing past the rung that matched the problem because the next one sounded serious.
The ladder
Rung 1: one VM, systemd or Docker Compose. A $20–40/month box, Caddy in front, a managed Postgres beside it, deploys that are a pull and a restart. Unfashionable, and it carries a genuinely surprising amount of traffic. Its weakness isn't capacity, it's that one reboot is downtime and rollback is "check out the previous commit and hope."
Rung 2: a managed PaaS. Render, Railway, Fly, Heroku. Push a branch, get a URL, health checks, zero-downtime deploys, managed databases, logs you didn't configure. You pay roughly a 2–3× premium over raw compute for not employing someone to build that, and under about ten engineers the premium is cheaper than the engineer. There's a longer comparison of Vercel, Railway and Fly if you're picking between them.
Rung 3: a scheduler you don't operate. ECS Fargate, Cloud Run. Real orchestration, autoscaling, IAM-native, inside your own VPC, no control plane to upgrade. Cloud Run scales to zero, which makes staging nearly free. This rung is the most underrated thing in cloud infrastructure, and it's where a large share of teams currently on Kubernetes belong.
Rung 4: managed Kubernetes. EKS, GKE, AKS. The cloud runs the control plane, you run everything else, and "everything else" is larger than it looks from below.
Rung 5: self-managed Kubernetes. kubeadm, Talos, your own etcd. Legitimate on-prem or where economics demand bare metal. Otherwise it's a full-time job you haven't hired for.
Teams stop at rung 4. Most should have stopped at 2 or 3.
What rung 4 actually costs
First, the invoice. An EKS control plane is roughly $0.10/hour, about $73/month, per cluster. You won't have one cluster; you'll have dev, staging and prod, so that's around $220/month before a container of yours runs. GKE is shaped similarly, with a free-tier allowance that stops applying past the first cluster.
Then the node floor. Three availability zones means three nodes minimum, even at zero load. And small nodes are a trap: kubelet, kube-proxy, the CNI, the CSI driver, a log shipper and a metrics agent take a fixed slice of every node. On a 2 vCPU box, that overhead plus your DaemonSets can eat a quarter of the machine before your app schedules. So you buy bigger nodes, and the idle floor is a few hundred dollars a month.
Then the parts nobody counts as "Kubernetes": an ingress controller, cert-manager, external-dns, metrics-server, Karpenter, a secrets CSI driver, an observability agent. Each is a Helm chart with a version, a set of CRDs, and a changelog you're now obliged to read.
The scheduler will also cheerfully place chatty pods in different zones, which arrives later as one of those AWS line items nobody chose.
The line item that isn't on the invoice
The question I ask before anyone says "let's use Kubernetes" is now two words long: who upgrades it?
EKS supports a given minor version for about fourteen months, and minors ship a few times a year. That's a cluster upgrade every four to six months, forever: read the deprecated API list, audit every chart against it, upgrade the control plane, roll the node groups, find the thing that broke. A day of work when it goes well.
The second question is: who gets paged for it? Platform on-call is not product on-call. When a pod is in CrashLoopBackOff at 2am, whoever answers has to distinguish between a broken app, a node out of memory, a PVC that won't attach, an admission webhook blocking every deployment in the cluster, and a DNS problem inside the CNI. Separate body of knowledge, and it decays if only one person has it.
If you can't name two people who'll own that, you don't have a platform team. You have one engineer with an expensive hobby, and they'll take it with them when they leave.
When it genuinely earns its keep
I want at least three of these before I'd say yes:
- Service count in the double digits. Past fifteen or twenty services, gluing together Fargate task definitions and load balancers costs more than a cluster does.
- Real multi-tenancy. Namespaces, network policies, quotas and RBAC as an isolation requirement, not decoration.
- A platform team of at least two. Named people, in their job description, with time allocated.
- Actual bin-packing pressure. A compute bill big enough that going from 30% average utilisation to 70% is worth five figures a year. Below that, packing efficiency is a rounding error against the control plane and the salaries.
Portability is the fifth argument people make, and I don't accept it. Nobody's manifests are cloud-agnostic once you have load balancer annotations, IRSA and a storage class.
The one I got wrong
I moved a three-service product onto EKS, reasoning that we'd need horizontal pod autoscaling soon and it'd be cheaper to build it before the traffic arrived than after.
The traffic never arrived at that scale. What did arrive was an ingress controller upgrade that broke TLS on a Friday, a node group that wouldn't drain because a pod disruption budget was misconfigured, and about two months where I spent more evenings on the cluster than on the product. The scaling problem I'd pre-solved turned out to be an N+1 query in one endpoint. Fargate would have run that product for the whole period without me thinking about it once.
The cost wasn't the $73/month. It was that infrastructure became a thing I maintained rather than used.
Going down a rung is not a demotion
The pressure to run Kubernetes is mostly social. It's what serious infrastructure looks like in conference talks, and it's what a résumé wants.
The right rung is the highest one you can operate without a dedicated person, and one lower if you're honest about vacations. If you're on rung 4 and can't name your platform owner, the move isn't to hire one. It's to drop to rung 3 and give that headcount to the product. Same argument as why I reach for boring technology: complexity you don't operate is free, complexity you do operate never is.