Why I Ditched Kubernetes for Local Development
Every week in a Slack channel or Reddit thread, someone drops the unsolicited advice: “You should be using Kubernetes locally.”
They’re not evil people. They’re just solving a problem they have, not the problem I have.
I’ve run Kubernetes in production. I’ve debugged crashed pods at 2 AM, deciphered kubectl describe output until my eyes bled, and spent days tuning Helm charts for something that should have been a 20-line Docker Compose file.
Then I went back to Docker Compose for local development. Here’s why.
The Kubernetes Hype Cycle
Let me get this out of the way: Kubernetes is genuinely impressive technology. If you’re running microservices at scale, need rolling deployments with zero downtime, or are orchestrating hundreds of containers across multiple nodes — k8s is the right answer.
But here’s what happens in the dev community:
- Big tech blog posts about how they run k8s in production
- Devs conclude k8s must be the “professional” way
- They install Minikube or kind and try to run their 3-service app
- Two hours later, they’ve written more YAML than application code
- They either give up or spend the next 6 months maintaining their “simple” local setup
The tooling around local k8s has gotten better. KIND (Kubernetes IN Docker) exists. k3s is lightweight. Lens makes the dashboard tolerable. None of this changes the fundamental problem: local k8s adds massive complexity for zero benefit on most projects.
What Kubernetes Actually Solves
To understand why I ditched k8s locally, you need to understand what it actually solves:
Problems k8s is designed for:
- Service-to-service load balancing across dozens of pods
- Horizontal pod autoscaling based on CPU/memory metrics
- Rolling deployments with zero-downtime updates
- Secret management across distributed services
- Cross-node networking in multi-node clusters
- Self-healing when containers crash and need rescheduling
Problems k8s creates for local dev:
- Every service needs a
Deployment,Service, and usually anIngressdefinition kubectlcommands are verbose and error-prone- Resource limits, health checks, liveness probes — boilerplate everywhere
- Multiple config files per service vs. one
docker-compose.yml - Your laptop becomes a k8s control plane (RAM usage: fun)
- teammates need to install and configure k8s just to run the project
If you’re not hitting the “problems k8s solves” list, you’re paying the complexity tax for nothing.
What I Use Instead: Docker Compose (Done Right)
After the k8s experiment, I went back to Docker Compose. But not the naive version — I’ve learned to use the patterns that actually matter in production.
Here’s my current docker-compose.yml for a typical API project:
services:
api:
build:
context: ./api
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
- REDIS_URL=redis://cache:6379
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=myapp
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
cache:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
migrate:
build:
context: ./api
dockerfile: Dockerfile
depends_on:
db:
condition: service_healthy
command: npm run db:migrate
restart: "no"
volumes:
pgdata:
The key patterns you need:
- Health checks on every service — no startup race conditions
depends_onwithcondition: service_healthy— waits for DB, not just “container started”- Restart policies — containers that stay up, stay up
restart: "no"for one-shot jobs like migrations — they shouldn’t restart on failure
This is production-adjacent. You can test health checks, verify startup ordering, and mirror this exactly in CI.
The Real Question to Ask
Before you reach for Kubernetes, ask yourself:
“What problem do I have that Docker Compose cannot solve?”
If the answer is “none” — and for 90% of projects, it is — you’re done. Use Compose.
If you need:
- Multi-node simulation (for distributed systems debugging)
- Kubernetes-specific features (CronJobs, StatefulSets, custom operators)
- Production parity that genuinely requires k8s semantics
Then use kind or Minikube. But scope it to the specific thing you actually need to test.
The Counter-Argument (And Why It’s Wrong)
“But our production runs Kubernetes!”
Yes, and you should test against that production setup. But that doesn’t mean your local environment needs to be a k8s cluster. Here’s what you should actually be testing locally:
- Your application’s behavior (does the code work?)
- Service dependencies (does your API talk to the DB correctly?)
- Health checks (does the service report healthy?)
- Startup ordering (do things come up in the right order?)
- Configuration (do your environment variables work?)
All of this works with Docker Compose. You don’t need pods, nodes, or kube-api to test your application code.
The k8s fans will say: “But you should test your Kubernetes manifests!”
Fair point. But those manifests should be tested in a test environment (CI), not necessarily on your laptop. Separate the concerns: local development is for writing application code, CI is for validating infrastructure.
Bottom Line
I spent 3 months running Kubernetes locally. It was technically interesting and practically useless for my workflow.
Docker Compose, used with proper health checks and startup ordering, handles every local development scenario I’ve encountered in 10 years of production code. It starts fast, it reads in one file, and everyone on the team can run it without a CS degree in cluster management.
Stop treating Kubernetes as the default for local development. Treat it as the power tool it is — reach for it when you actually need it.
What’s your local dev stack? Still fighting with k8s? Drop it in the comments — I’ve heard the other side of this argument and I’m open to being convinced.
Related Articles
- Docker Compose Patterns Every Developer Should Know — health checks, volumes, and networks done right
- Why Senior Devs Still Prefer Vim in 2026 — another controversial take on “the right tool”
- PostgreSQL Tricks I Wish I Knew 5 Years Ago — database patterns that actually matter
📚 Continue Reading
Supporting the blog through affiliate links (at no extra cost to you):
- Kubernetes Up & Running (Kelsey Hightower) — if you're going to learn k8s, learn from the best
- Effective Java — still the best Java book I've read
- The Pragmatic Programmer — timeless advice for devs at any level
Enjoying the content? Here are tools I personally use and recommend:
- 🌐 Hosting: Bluehost — what this blog runs on
- 🛒 Tech Gear: My Amazon Store — keyboards, monitors, dev tools I use
Purchases through my links help keep this blog ad-free 💙
Enjoyed this post?
Subscribe to the newsletter or follow on YouTube for more dev content.
🎬 Watch Shorts