There is a moment in every side project where you catch yourself opening the Kubernetes docs, and you need someone to ask you a simple question: how many users do you have? If the honest answer is "me, and sometimes my friend testing on staging", close the tab.
I run the infrastructure for a healthcare platform as its only developer. Somewhere along the way I started writing down the rules I kept re-deriving from scratch, and it grew into a full set of internal DevOps guidelines: eighteen parts covering everything from networking standards to cost management. The single most useful idea in all of it fits in one sentence: Kubernetes is not a badge of engineering maturity. It is an operational tool.
Tools have prerequisites. A hammer assumes you have nails. Kubernetes assumes you have a team that can operate it at three in the morning, workloads that actually need orchestration, and enough services that scheduling them by hand became painful. If those assumptions do not hold, you have not adopted Kubernetes, you have adopted its bill.
The framework I use instead is a staged one. I keep a table with five stages, from prototype to internet scale, and each stage lists two things: what you should be running, and what you should explicitly avoid. The avoid column is the important one. At the prototype stage, avoid Kubernetes, avoid microservices, avoid multi-region, avoid anything with the word "mesh" in it. Not because those things are bad, but because they solve problems you do not have yet, and they charge rent whether or not the problem shows up.
The mechanism behind the table is what I call a complexity budget. Every system can only afford so much operational complexity, and the budget is set by the team size and the stakes, not by ambition. A solo developer has a tiny budget. Spending it on container orchestration means there is nothing left for the things that actually kill small products: backups you never tested, monitoring you never set up, deploys you are scared of.
That last one deserves its own line, because another rule from the guidelines follows me around: an untested backup is an assumption, not a recovery plan. It is amazing how many teams have Kubernetes and no restore drill.
For every piece of heavyweight infrastructure, the guidelines define a gate: a set of concrete conditions that must be true before adopting it. The Kubernetes gate asks about team size, service count, and whether deployment pain is actually the bottleneck. The microservices gate asks whether independent teams need independent deploy cadences. The multi-region gate asks whether you have users whose regulators or latency budgets demand it. Most projects never pass most gates, and that is the point.
When two rules conflict, I resolve them with a fixed priority order: reliability first, then security, then simplicity, and cost near the end. The order is not the interesting part. The interesting part is having one at all, because it turns arguments into lookups. Should I add a second region for resilience, at triple the operational complexity? Reliability says maybe, simplicity says no, and the tie-break rules say simplicity loses only when reliability is actually threatened. One availability zone going down is rare; me being unable to operate a two-region setup alone is guaranteed.
None of this means staying small forever. Stages exist to be graduated from. When DokLink needs more than one server can give, the same table tells me what the next stage looks like and what it costs. The framework does not forbid complexity, it prices it, and it makes me pay attention to the receipt.
The uncomfortable truth about resume-driven infrastructure is that it optimizes for interviews you have not gotten at the expense of users you already have. The systems I am proudest of are boring: a Django monolith, PostgreSQL, Docker, Nginx, one server, tested backups. Boring is what reliable looks like from the inside.
So before the next kubectl tutorial, ask the staged question: what stage am I actually at, and what does that stage say to avoid? The answer is usually cheaper, simpler, and slightly disappointing. Ship it anyway.