You've outgrown managed container services but you're not sure if Kubernetes is worth the operational overhead. The question isn't whether Kubernetes is powerful—it is—but whether EKS is the right fit for your team and workload. In this post, I'll walk through when Kubernetes on AWS makes sense, what costs hide beyond the bill, and when to stick with simpler alternatives.
Good fit — Many services, existing Kubernetes skills, portability needs
EKS makes the most sense when you hit a few specific conditions at once. First, you're running enough microservices that orchestration overhead becomes worth it. I'm talking about teams managing 20+ containers across different deployment patterns—cron jobs, long-running APIs, background workers, and stateful services.
Second, your team already knows Kubernetes or you have the bandwidth to learn it properly. I've seen teams adopt EKS because "it's the standard" only to struggle with node pool management, networking policies, and RBAC. Kubernetes expertise isn't optional; it's the entry fee.
Third, and this matters more than people admit, you need portability. If you might run workloads on GKE, AKS, or on-premises clusters down the line, Kubernetes gives you that flexibility. Your deployment manifests, Helm charts, and operational patterns port across clouds. I've worked on platforms that started on EKS and later needed to run in both AWS and a customer's private data center—that portability was genuine business value.
Let me walk through a realistic scenario. You're building a SaaS platform with:
- Three API services (user auth, billing, core product)
- Five background workers (email delivery, report generation, webhooks, image processing, cache warming)
- A legacy monolith still running alongside new services
- Ad-hoc Jupyter notebooks and ML model serving
- A batch job that runs nightly and scales from 2 to 50 workers
ECS could handle this, but you'd write separate task definitions for each workload pattern. With EKS, a single deployment manifest and Keda autoscaling rules handle your batch job scaling elegantly. Your team uses kubectl apply -f deployment.yaml consistently across every service type.
Compare that to an ECS setup where you're managing task definitions, ECS services, and separate autoscaling configurations. Not impossible, but cognitively heavier.
Costs beyond the bill — Upgrades, add-ons, networking and security policies
Everyone knows the EKS cluster fee: $0.10 per hour. That's $73 a month just to exist. But the real costs hide in operational complexity and infrastructure dependencies.
Cluster upgrades. EKS patches happen regularly. You can't just ignore them—Kubernetes versions go unsupported, and security fixes matter. Each upgrade touches your node groups, requires testing, and can break third-party add-ons. I've spent entire afternoons debugging a CoreDNS version mismatch after a cluster upgrade. With ECS, you get patches for free without the coordination ceremony.
Add-ons and controllers. Your cluster won't run properly without extras:
- VPC CNI for pod networking
- CoreDNS for service discovery
- kube-proxy for iptables rules
- Keda or HPA for autoscaling
- Ingress controller (NGINX, ALB controller)
- Cert-manager for TLS
- A metrics server for monitoring
- Pod security policies or Kyverno for policy enforcement
Each of these is a dependency you monitor, patch, and troubleshoot. That's real operational weight.
Networking and security policies. Kubernetes networking is powerful but intricate. I've seen production incidents where a single misconfigured NetworkPolicy blocked all traffic between services. Here's a real example I dealt with:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432These policies are necessary for security, but they require careful planning. One typo in a label selector and your services can't talk to each other. With ECS, you use security groups—simpler, though less granular.
The hidden cost. If you're running a small team with tight deadlines, every hour spent debugging a Kubernetes issue is an hour not shipping features. That's the real cost you need to measure.
Managed helpers — Managed node groups, Fargate profiles and Auto Mode reduce work
AWS has built tooling to reduce the operational burden. These features matter—they're the difference between EKS being reasonable and EKS being a nightmare.
Managed node groups. Instead of managing EC2 instances yourself, you define a node group and EKS handles the AMI, patching, and rolling updates. Here's what that looks like:
aws eks create-nodegroup \
--cluster-name my-cluster \
--nodegroup-name production-nodes \
--subnets subnet-12345 subnet-67890 \
--node-role arn:aws:iam::123456789:role/EKSNodeRole \
--scaling-config minSize=3,maxSize=20,desiredSize=5 \
--instance-types t3.large m5.large \
--tags Environment=production Team=platformAWS handles OS patches, EKS agent updates, and coordinated drains during upgrades. Without this, you're managing launch templates, AMI IDs, and manual upgrade orchestration. Huge difference.
Fargate profiles. If you don't want to manage nodes at all, Fargate lets you specify pod requirements and AWS provisions the compute. Your billing is per-pod-per-second, so it's expensive for always-on services but excellent for burstable workloads.
aws eks create-fargate-profile \
--cluster-name my-cluster \
--fargate-profile-name background-workers \
--pod-execution-role-arn arn:aws:iam::123456789:role/EKSFargatePodExecutionRole \
--subnets subnet-12345 subnet-67890 \
--selectors namespace=workers,labels="workload-type=background"I've used this pattern for scheduled jobs and one-off workers. You avoid idle node costs, and scaling is automatic. The trade-off: you can't customize the underlying OS or install system packages, and cold start latency can be 30-60 seconds.
EKS Auto Mode (newer). This is still relatively new, but it's AWS's answer to "we want Kubernetes without the toil." You specify your workload requirements and Auto Mode manages everything—node provisioning, patching, networking. It's Kubernetes for people who want Kubernetes abstractions without Kubernetes operations.
Early in a project, I'd lean toward this if my team isn't deeply Kubernetes-invested. The cost premium is real, but the operational simplification matters.
Start simpler — ECS covers most needs with less operational load
Here's the uncomfortable truth: ECS handles the majority of microservice workloads with a fraction of the complexity.
ECS is AWS-native. You define task definitions, services, and let CloudFormation or Terraform manage the rest. Scaling is built in through service autoscaling and capacity providers. Deployments are atomic—you can't partially deploy a broken version. Networking lives within your VPC with standard security groups. No custom policies, no label selectors, no network plugin versions.
I built a production platform with ECS for three years before we migrated to EKS. We had 12 services, 40+ containers, complex autoscaling, and state management. ECS handled it beautifully. We moved to EKS because we added a Kubernetes-native third-party tool (ArgoCD) and wanted to run it alongside our stack. That was a legitimate reason—not a theoretical one.
Here's when ECS is genuinely better than EKS:
- Small teams. You don't want to maintain Kubernetes infrastructure alongside shipping features.
- Steady workloads. Your traffic patterns are predictable; you don't need sophisticated pod scheduling.
- AWS-first. You're not considering multi-cloud deployment in the next two years.
- Cost-sensitive. Every dollar matters; ECS has lower operational overhead.
- Integration-heavy. You're deeply embedded in AWS services (AppMesh, CloudWatch, service discovery via Route 53).
A realistic ECS example:
aws ecs create-service \
--cluster production \
--service-name api-service \
--task-definition api:5 \
--desired-count 3 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-12345],securityGroups=[sg-98765]}" \
--load-balancers targetGroupArn=arn:aws:elasticloadbalancing:...,containerName=api,containerPort=8080That's it. Add CloudWatch autoscaling rules and you have self-healing, auto-scaling workloads. No cluster upgrade ceremonies, no add-on patching, no NetworkPolicy debugging.
Common mistakes
- Adopting EKS without Kubernetes literacy. Your team will struggle. Invest in training or start with ECS.
- Underestimating the cost of ingress and networking. Default VPC CNI can waste IP addresses; custom networking adds complexity. Plan this before deployment.
- Running too few nodes. Pod evictions during node failures are painful. Overprovision slightly; the insurance is worth it.
- Forgetting about pod disruption budgets. Cluster upgrades will kill your pods. Without PDBs, your services go down unnecessarily.
- Mixing managed nodes and Fargate randomly. Decide your strategy upfront; mixing adds operational inconsistency.
Key takeaways
- EKS makes sense when you have 20+ containers, Kubernetes expertise on your team, and portability needs. Otherwise, it's probably overengineered.
- The real cost of EKS is operational complexity: upgrades, add-ons, networking policies, and incident debugging. Budget for that, not just the cluster fee.
- Managed node groups and Fargate profiles significantly reduce toil. Auto Mode is worth exploring if you want Kubernetes abstractions without Kubernetes operations.
- ECS is simpler, faster to operate, and perfectly adequate for most microservice platforms. Only move to EKS when you have a concrete reason—not because it's "the industry standard."
- Start with ECS, graduate to EKS. The reverse migration is painful.






Comments
Loading comments…