İçeriğe geç
wedevit

August 24, 2026 · 9 min read · infrastructure

İlhan Buğra Aslan

Do you really need Kubernetes? Choosing between a single server, managed containers and serverless


Kubernetes is not a maturity level. It solves one specific problem: packing many independently deployable workloads onto a shared pool of machines and managing them through a single declarative interface. Most teams running one application, or three or four services, do not have that problem, which is why the right answer for them is usually a boring server or a managed container platform. Three questions settle the decision: how many independently deployable pieces you have, how many hours a month your service has to stay warm, and whose phone rings at 3am. Price lists follow from those answers rather than leading them.

Four options, four different ownership boundaries

The choice is less about technology than about where your responsibility stops.

  • A single virtual machine. The machine is yours. OS patching, the reverse proxy, certificate renewal, backups and restore drills all stay with you.
  • A managed container platform. The boundary is the container image. You hand over an image and a few settings; rolling releases, health checks, autoscaling and TLS are the platform's job. Cloud Run, Azure Container Apps, App Runner, Fly and Render sit here.
  • Kubernetes. The boundary is the cluster itself. You now operate not just your application but the API that manages your application: version upgrades, the ingress controller, storage and network plugins, resource requests.
  • Serverless functions. The boundary is a single request handler. Scaling and resilience move to the provider, and in exchange your application's shape gets constrained.

This is not a ladder. You are not obliged to start at the bottom and climb, and being higher up is not better engineering.

What Kubernetes actually solves

It does three things genuinely well: placing many workloads onto a shared pool of machines, returning whatever died to the state you declared, and drawing resource, network and permission boundaries between teams. All three start with the word "many". If you run one web app, one background worker and a database, you have no placement problem. You have one thing to place, and putting it on a machine is called installation, not scheduling.

The bin-packing win also does not arrive on its own. Cast AI's 2026 resource optimization report puts average CPU utilization at 8% and memory at 20% across tens of thousands of production clusters, with CPU overprovisioning climbing from 40% to 69% in a year and memory at 79%. Most of the capacity teams request is never used. Kubernetes can pack workloads densely, but it will not do so unless someone measures requests and tightens them. A team that will not do that measurement buys the bill without the architectural benefit.

The control plane meters before a single pod runs

Amazon EKS charges $0.10 per cluster per hour for the control plane, roughly $73 a month. Open separate clusters for development, staging and production and you are at about $219 a month before a single workload runs. Google's GKE charges the same fee, though it grants a monthly credit per billing account that covers one zonal or Autopilot cluster. Azure AKS gives you free cluster management on its Free tier, at the price of no financially backed uptime SLA, and Microsoft recommends that tier for development and test clusters under 10 nodes. Production SLA coverage means moving to a paid tier.

The real line items start after that: nodes, load balancers, a NAT gateway, persistent disks and egress traffic. A small internal business application can run happily on a virtual server costing single-digit euros a month, while the cluster you open for the same application creates a three-figure floor on day one. That floor is not a problem in itself, it just needs something on the other side of the trade. Usually the other side is more than one team shipping through more than one independent pipeline.

Upgrading is a subscription, not a project

Kubernetes ships three minor releases a year and maintains only the three most recent branches. As of today the supported versions are 1.34, 1.35 and 1.36, going end of life on 27 October 2026, 28 February 2027 and 28 June 2027 respectively. Each minor version gets about a year of patches, or 14 months counting the upgrade window. The practical consequence is that whoever builds the cluster has signed up for at least one version upgrade a year, forever.

Deferring that work has a published price. On EKS, standard support for a version lasts 14 months, after which the cluster moves automatically into extended support and the hourly rate goes from $0.10 to $0.60. Six times the price, roughly $438 a month, for up to 12 more months. On Azure, the Premium tier sells long-term support for up to 24 months. Both are saying the same thing: "we will upgrade later" is a debt item, and this time the interest rate is a list price rather than an estimate (see measuring and prioritizing technical debt).

With serverless, the real limit is shape rather than price

The fixed numbers in AWS Lambda are specific enough to make the decision on their own:

  • Function timeout caps at 900 seconds, or 15 minutes.
  • Memory runs from 128 MB to 10,240 MB, and at 1,769 MB you get the equivalent of one vCPU.
  • Synchronous request and response payloads are 6 MB each (200 MB for streamed responses), and 1 MB for asynchronous invocations.
  • A zip deployment package is 250 MB unzipped; a container image can be 10 GB.
  • Default concurrency is 1,000 per region, and each execution environment serves up to 10 requests per second. New accounts start with lower quotas.

What matters is the character of that list rather than its length: short-lived, stateless work that finishes inside one request. AWS has widened the envelope over time, and there are now MicroVMs that run up to eight hours plus durable functions for stateful workflows. The classic function shape has not changed, though. If you have a 45-minute batch job, a 60 MB report to generate or a WebSocket that needs to stay open, the argument ends on shape, not cost.

The cold start debate is usually held in the wrong place

AWS documents the numbers plainly: cold starts typically occur in under 1% of invocations, they last from under 100 ms to over a second, and they are more common in development and test functions than in production because those functions get called less often. For most workloads, average latency is not the issue.

Two other things are. First, tail latency on the path a user is waiting on: a one-second p99 on a checkout step cannot be defended by pointing at the average. Provisioned concurrency fixes it, with money, and it erases the scale-to-zero advantage in the process. Second, database connections: every execution environment opens its own pool, a hundred concurrent environments want a hundred connections, and the database is the first thing to hit a limit. We covered pooling and connection ceilings in database bottlenecks and slow queries.

Counting monthly hours settles half the decision

The rule is simple. If your workload has to stay warm for most of the month, per-second billing works out expensive; if traffic is spiky and infrequent, it works out cheap. Cloud Run bills per vCPU-second and GiB-second and can scale to zero when no requests arrive. Its request timeout defaults to 5 minutes and maxes out at 60, and Google advises that anything past 15 minutes should be idempotent or resumable. That advice is an architecture warning in its own right: long jobs belong in a queue, not inside a request.

Here is the practical test. Write down how many hours a month the service genuinely does work. If it is all 730 hours of the month, what you are renting is a server whatever the product is called, and reserved capacity is almost always cheaper. If it is 5% of the month, most of what you pay for a permanently running node is waste. We went through where cloud bills quietly accumulate in cutting cloud costs for good.

For most teams the answer is a managed container platform

The default recommendation that falls out of all this is plain: a Dockerfile, an image, a URL. Rolling releases, health checks, autoscaling, TLS and log collection come with the platform, and there is no API server for you to upgrade. Going from one service to five does not mean learning a new platform, because the fifth service is just another image.

The limits are equally clear. Service-to-service networking primitives are thin, sidecar support is not universal, and scaling and identity settings are provider-specific. One rule keeps that manageable: keep the image portable, keep configuration in environment variables, and always keep a path that runs locally with docker run. Probes, draining in-flight requests during shutdown and the ordering of schema changes stay your problem either way, and we collected that side of it in zero-downtime deployments.

A single server is nothing to apologize for, if five things are written down

Plenty of production systems have stayed up for years on systemd, a reverse proxy and a deploy script. What makes that defensible is not its simplicity but the presence of five things: an image or script that rebuilds the machine identically from scratch, automated OS patching, a backup someone has actually restored, a second machine you can promote when the first one dies, and basic monitoring that raises an alarm. Miss one of the five and the single server is not cheap, it is just deferred cost.

Two warnings. On security, a managed platform patches the runtime for you, while on your own machine the kernel and library updates stay with you; we mapped exactly where that line falls in cloud misconfiguration and shared responsibility. On price, cheap server listings are not fixed: Hetzner updated its price list on 15 June 2026 for new orders and instance rescales. Do not build a business model on one provider's current rate card.

Going back to your own hardware: what the 37signals case proves

The case everyone cites is 37signals. Their annual cloud bill was $3.2 million in 2022. In 2023 they bought roughly $700,000 of Dell hardware and moved seven applications off the cloud in six months. By 2024 the bill was down to $1.3 million, close to $2 million saved, and their founder wrote that five-year savings would top $10 million. In 2025 they moved the remaining S3 workload onto 18 petabytes of their own flash storage.

What that proves: when load is large and predictable, owning can beat renting. What it does not prove: the team doing it has people who own the hardware lifecycle, their own deployment tooling and two separate data centres. A team with a four-figure monthly bill cannot reproduce the arithmetic, because the expensive input there is attention rather than hardware. If your cloud spend has reached tens of thousands a month and your traffic graph is a flat line, the calculation is worth doing. Below that, it is not.

Which layer creates the lock-in

Portability runs roughly like this: a container image travels anywhere, Kubernetes manifests travel but managed add-ons (ingress controllers, identity integrations, storage drivers) do not, and serverless handlers plus their event bindings travel least of all. That is not a list of things to avoid, it is a budget line. The layer you pick sets the bill you pay if you want to move in three years.

Keeping that bill low is a matter of drawing the boundary in code. Write business logic behind an interface rather than inside the provider's SDK, and keep queue, storage and scheduler calls in one place. In an application written that way, changing platforms is a migration project instead of a rewrite.

A first step that fits in this week

Write five lines. One: how many independently deployable pieces do you have, and do they genuinely ship separately? Two: how many hours a month does the service have to stay warm, and what is peak over average? Three: whose phone rings at 3am, and what is that person authorized to fix? Four: who owns version upgrades, and on what schedule? Five: how long is the list of things you would have to move if you left this platform?

If questions two and three have no answer, the platform choice is premature; measurement and an on-call rota come first (observability, SLOs and error budgets). If the answer to question one is "one", read monolith or microservices before moving the argument to service boundaries, because the need for Kubernetes usually originates there. Whichever platform you pick, automating the release remains the highest-return step even on a single machine (CI/CD for small teams).


Need help with this topic?

get in touchall posts