Running K8s for a side project (don't)
I ran Kubernetes for a side project. One service, a database, a cron, and a few hundred users on a good day. I did it so that you don’t have to — and so I could say, from experience rather than vibes, that it was the wrong call.
To be clear: K8s is excellent at what it’s for. This isn’t a rant against the tool. It’s a story about applying a fleet-scale solution to a single-VM problem because the resume part of my brain was driving.
What I told myself I needed
“It’ll scale.” “I’ll learn it properly.” “Zero-downtime deploys.” “It’s basically industry standard.” Each of these is true in a context, and none of them was my context. I had one stateless service, one Postgres, and traffic that a Raspberry Pi would yawn at.
What I actually wanted was: deploy without thinking, don’t lose data, come back in three months and still understand it. K8s delivers the first poorly (for one service), the second only if you’re careful, and the third not at all.
What it actually cost
The cluster was never the work. The work was everything around it:
- YAML, endless YAML. Deployments, services, ingress, secrets, config maps, a cert-manager dance, resource limits I guessed at.
- An ingress controller and TLS that broke in ways that required learning the controller’s internals to debug.
- Stateful pain. Running Postgres in-cluster is a trap; running it out-of-cluster means you didn’t need the cluster for the hard part.
- Upgrades. The cluster itself needs maintenance. The thing meant to run my app became an app that needed running.
- The bill. A control plane plus nodes sized for redundancy, to serve traffic a single small VM handles without noticing.
Months later I came back to ship a one-line change and spent the evening remembering how my own cluster worked. That’s the tell. Infrastructure you have to relearn is infrastructure that’s too heavy for the job.
The boring alternative
Here’s what I replaced it with, and what I’d start with next time:
# one small VM, and a deploy that fits in your head
git pull
docker compose up -d --build # app + caddy for TLS
# postgres: managed, or a second container with a real backup cron
A single VM, Docker Compose, Caddy terminating TLS with automatic certs, and a managed Postgres (or a ruthlessly tested backup script). Deploys are git pull && up. Logs are docker compose logs. When I come back in three months, the whole system fits on one screen and in my head.
It doesn’t auto-scale. It doesn’t need to. The honest scaling plan for a side project is “make a bigger VM,” and that plan is good until you have the kind of traffic that also gives you the budget and reason to graduate.
When K8s is actually right
Multiple teams shipping many services. Real horizontal scale. A platform team whose job is the cluster. Bin-packing that saves meaningful money. If you have those, the complexity earns its keep. A side project has none of them.
The complexity of your infrastructure should match the complexity of your problem — not the complexity of the job you’d like to be hired for.
The lesson
I learned a lot, which is the seductive justification. But I’d have learned more, shipped faster, and slept better by running the boring thing and spending the saved time on the actual product. Choosing dull, legible infrastructure is a senior move; reaching for the cluster is usually the opposite, dressed up as foresight.
So: run the single VM. Keep the Postgres boring. Spend your complexity budget where the problem is hard — which, for a side project, is almost never the infrastructure.
Filed under systems. Disagree, or scaled past the VM honestly? Tell me how it went.