Kubernetes gets adopted by teams that don't need it far more often than it gets skipped by teams that do — it's genuinely powerful infrastructure, and genuinely overkill for the majority of projects that reach for it anyway.
Kubernetes is a container orchestration platform that automates deploying, scaling, and managing containerized applications across a cluster of machines. It handles scheduling containers onto available nodes, restarting failed containers, load-balancing traffic between replicas, and rolling out updates without downtime — solving real operational problems, but only ones that actually exist once you're running containers at meaningful scale.
Why Kubernetes Matters (and When to Skip It)
At real scale — many services, variable load, multi-region deployment — manually managing where containers run, how they're networked, and how they recover from failures becomes untenable. Kubernetes automates all of it through a declarative model: you describe the desired state (three replicas of this service, this much CPU/memory), and Kubernetes continuously works to make reality match that description.
Skip Kubernetes for small-to-medium applications that a managed PaaS (Railway, Fly.io, Vercel) or even a single well-configured server handles fine — the operational complexity Kubernetes adds (learning curve, cluster management, YAML sprawl) is a real cost that needs a correspondingly real scaling problem to justify.
Getting Started with Kubernetes
A basic Deployment and Service, the two most common resource types:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-registry/my-app:1.0.0
ports:
- containerPort: 3000
resources:
requests: { cpu: "100m", memory: "128Mi" }
limits: { cpu: "500m", memory: "512Mi" }
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
kubectl apply -f deployment.yaml -f service.yaml
kubectl get pods
Core Kubernetes Concepts Every Developer Should Know
Pods are the smallest deployable unit, typically wrapping a single container (though they can hold more). You almost never create Pods directly — a Deployment manages Pods for you, handling replication and rollout.
Deployments handle rolling updates with zero downtime by default. Updating the image version in a Deployment spec triggers a gradual replacement of old Pods with new ones, keeping the service available throughout:
kubectl set image deployment/my-app my-app=my-registry/my-app:1.1.0
kubectl rollout status deployment/my-app
kubectl rollout undo deployment/my-app # rollback if something's wrong
Services provide stable networking for a set of Pods that come and go as Deployments scale or restart them — a Service gives you a consistent address to route traffic to regardless of which specific Pods are currently running.
Resource requests and limits are not optional in practice. Without them, a single misbehaving Pod can starve every other workload on the same node of CPU or memory. Setting requests and limits deliberately for every workload is one of the most important operational disciplines in a real Kubernetes deployment.
Common Kubernetes Mistakes and How to Fix Them
Mistake 1: no resource requests/limits set. This is consistently one of the most common causes of cluster instability — one workload consuming unbounded resources degrades everything else on the same node. Fix: set explicit requests and limits for every container based on actual observed usage.
Mistake 2: adopting Kubernetes before there's an actual scaling problem to solve. Teams that reach for Kubernetes for a handful of low-traffic services take on real operational overhead without a corresponding benefit. Fix: honestly assess whether a managed PaaS covers your actual needs before committing to Kubernetes's complexity.
Mistake 3: not using liveness/readiness probes. Without them, Kubernetes can't tell whether a Pod is actually healthy and ready to receive traffic, leading to requests routed to Pods that are still starting up or already broken. Fix: define both probes for every service, tailored to what "healthy" actually means for that specific app.
When Should You Use Kubernetes Instead of a Managed PaaS?
Use Kubernetes when you're running many services at real scale, need fine-grained control over networking/scheduling/resource allocation, or have specific multi-cloud/on-prem requirements a PaaS can't meet. Use a managed PaaS (Railway, Fly.io, Render, Vercel) when your scale and complexity don't yet demand Kubernetes's control, and you'd rather trade some flexibility for dramatically less operational overhead.
Kubernetes in Production
Use a managed Kubernetes offering (EKS, GKE, AKS) rather than self-hosting the control plane unless you have specific reasons not to — control plane management is significant undifferentiated operational work. Also invest in observability (metrics, logging, tracing) from the start; debugging a distributed system without proper observability tooling is exponentially harder than debugging a single server.
Before adopting Kubernetes for a new project, honestly answer whether a managed PaaS would actually be insufficient — if you're not sure, that uncertainty itself is a signal you probably don't need Kubernetes yet.