The most expensive mistake in cloud isn't over-provisioning a server — it's choosing the wrong compute model for your workload. Running event-driven functions on EKS? Over-engineered. Running a 24/7 API with 10-second cold starts on Lambda? Under-engineered. Both cost you money, time, and pain.
AWS offers six primary compute options, and they're not interchangeable. This guide provides a decision framework based on workload characteristics — not vendor hype.
The Compute Spectrum
MORE CONTROL LESS CONTROL
MORE RESPONSIBILITY LESS RESPONSIBILITY
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ EC2 │ │ECS on│ │EKS on│ │Fargate│ │App │ │Lambda│
│ │ │ EC2 │ │ EC2 │ │ │ │Runner│ │ │
│You own│ │You │ │You │ │No │ │Just │ │Just │
│every- │ │manage│ │manage│ │servers│ │deploy│ │code │
│thing │ │nodes │ │nodes │ │ │ │image │ │ │
└──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘
Quick Decision Matrix
| If your workload is... | Use... | Why |
|---|---|---|
| Event-driven, < 15 min, bursty | Lambda | Pay per invocation, scales to zero |
| HTTP API, predictable traffic | ECS + Fargate or App Runner | Simplest container path |
| Microservices, 5-15 services | ECS + Fargate | AWS-native, simple, low ops |
| Microservices, 15+ services, CNCF ecosystem | EKS | Kubernetes portability + ecosystem |
| GPU workloads, ML training | EC2 (or SageMaker) | GPU instance control |
| Legacy apps, specific OS/kernel needs | EC2 | Full machine control |
| Batch processing, parallel compute | AWS Batch (on Fargate or EC2) | Managed job scheduling |
| Real-time data streaming | ECS/EKS with persistent connections | Long-lived processes |
EC2: Full Control, Full Responsibility
Choose EC2 when:
- You need specific instance types (GPU, FPGA, bare-metal)
- Workload requires kernel customization or specific OS configurations
- Running licensed software tied to machine/CPU
- Need persistent local storage (instance store NVMe)
- Maximum performance with minimal abstraction
Don't choose EC2 when:
- You just need to run containers (use Fargate instead)
- Workload is event-driven and bursty (Lambda is cheaper)
- You don't want to manage patching, AMIs, and Auto Scaling groups
EC2 Cost Optimization
| Strategy | Savings |
|---|---|
| Graviton (ARM) instances | 20-40% better price/performance |
| Spot Instances | Up to 90% for fault-tolerant workloads |
| Savings Plans | Up to 72% for steady-state |
| Right-sizing (Compute Optimizer) | 20-30% by eliminating over-provisioning |
| Scheduled stop/start (dev/staging) | ~65% on non-production |
ECS (Elastic Container Service): AWS-Native Containers
Choose ECS when:
- You want the simplest container orchestration on AWS
- Your team doesn't know (or need) Kubernetes
- 5-15 microservices, all on AWS
- You want deep AWS integration (IAM task roles, Service Connect, CloudMap)
- No multi-cloud requirement
ECS on Fargate vs ECS on EC2
| Criteria | ECS + Fargate | ECS + EC2 |
|---|---|---|
| Server management | None | You manage ASG + AMIs |
| Cost at scale | Higher per-vCPU | Lower (especially with Spot/RIs) |
| Startup time | ~30 seconds | Instant (containers already on host) |
| GPU support | Limited | Full GPU instance access |
| Bin packing | AWS handles it | You optimize placement |
| Best for | Variable workloads, small-medium scale | High-scale, cost-sensitive, GPU |
ECS Architecture Pattern
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ ALB │────→│ ECS Service │────→│ RDS │
│ │ │ (Fargate) │ │ (Aurora) │
└─────────────┘ │ 3 tasks │ └──────────────┘
└──────────────┘
│
┌──────────────┐
│ Service │
│ Connect │──→ Other ECS Services
└──────────────┘
EKS (Elastic Kubernetes Service): The Kubernetes Path
Choose EKS when:
- Team already knows Kubernetes
- You need multi-cloud portability (same manifests on GKE/AKS)
- 15+ microservices benefiting from the CNCF ecosystem
- Need advanced traffic management (Istio, Linkerd)
- Want Karpenter for intelligent auto-scaling
- Need custom operators or CRDs for your domain
Don't choose EKS when:
- Your team doesn't know Kubernetes (learning curve is steep)
- < 10 services (ECS is simpler and cheaper)
- You're 100% AWS with no multi-cloud plans
EKS Cost: The $73/Month Control Plane
EKS charges $0.10/hour ($73/month) for the control plane. Add node compute on top. This makes EKS expensive for small workloads but negligible at scale.
EKS Compute Options
| Option | Best For | Cost Model |
|---|---|---|
| Managed Node Groups | Standard workloads, simple ops | EC2 instance pricing |
| Karpenter | Dynamic scaling, mixed instance types | Right-sized EC2 + Spot |
| Fargate | Isolation-sensitive, no node management | Per-pod vCPU/memory pricing |
| Spot + Karpenter | Cost-optimized batch/stateless | Up to 90% cheaper than On-Demand |
EKS Architecture Pattern
┌──────────────────────────────────────────────────┐
│ EKS Cluster │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ Namespace: │ │ Namespace: │ │Namespace:│ │
│ │ team-a │ │ team-b │ │ platform │ │
│ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ArgoCD │ │
│ │ │ pods │ │ │ │ pods │ │ │ Prometheus│ │
│ │ └─────────┘ │ │ └─────────┘ │ │ Grafana │ │
│ └─────────────┘ └─────────────┘ └──────────┘ │
│ │
│ Karpenter → Spot + On-Demand (Graviton) │
└──────────────────────────────────────────────────┘
Fargate: Serverless Containers
Choose Fargate when:
- You want containers without managing servers
- Workloads are variable (scale up/down frequently)
- Security requires task-level isolation (each task gets its own kernel)
- Team doesn't want to manage EC2 instances, ASGs, or AMI patching
Don't choose Fargate when:
- Cost is the primary concern at high scale (EC2 is 30-50% cheaper)
- Need GPU instances
- Need > 4 vCPU / 30 GB memory per task (Fargate has size limits)
- Need daemonsets or host-level access (use EC2 nodes)
Fargate Pricing Reality
Fargate is ~3x more expensive per vCPU-hour than equivalent EC2 On-Demand. But you save on:
- No idle capacity (pay only for running tasks)
- No ops time managing nodes
- No AMI patching or security updates on hosts
Break-even: If utilization stays above ~60-70%, EC2 is cheaper. Below that, Fargate wins because you're not paying for idle capacity.
Lambda: Serverless Functions
Choose Lambda when:
- Event-driven processing (S3 events, SQS messages, API calls)
- Execution time < 15 minutes
- Bursty, unpredictable traffic patterns
- You want zero infrastructure management
- Cost must scale to zero when idle
Don't choose Lambda when:
- Functions run > 15 minutes
- Need persistent connections (WebSockets, gRPC streams)
- Cold starts are unacceptable (use provisioned concurrency or Fargate)
- Workload is high-throughput steady-state (EC2/Fargate is cheaper)
- Need > 10 GB memory
Lambda Cost Calculation
Cost = (Requests × $0.20/1M) + (GB-seconds × $0.0000166667)
Example: 1M requests/month, 256MB, 200ms average
= $0.20 + (1M × 0.256GB × 0.2s × $0.0000166667)
= $0.20 + $0.85
= $1.05/month
Same workload on Fargate (0.25 vCPU, 512MB, always running):
= $9.47/month (vCPU) + $1.04/month (memory) = $10.51/month
Lambda is 10x cheaper for bursty workloads. But at 10M+ steady requests, Fargate wins.
App Runner: The Simplest Container Path
Choose App Runner when:
- You want the fastest path from container image to production URL
- Simple web applications or APIs
- Don't need VPC integration (or use VPC connector for private resources)
- Team has zero AWS infrastructure experience
App Runner vs Fargate:
| Feature | App Runner | ECS + Fargate |
|---|---|---|
| Setup complexity | Push image → done | Task def + service + ALB + target group |
| Auto scaling | Built-in, automatic | Configure scaling policies |
| Custom domains + TLS | One-click | ACM + ALB configuration |
| VPC access | Via connector | Native |
| Load balancing | Built-in | You configure ALB |
| CI/CD | Built-in (from ECR/GitHub) | You configure pipeline |
| Flexibility | Limited | Full control |
The Decision Flowchart
START
│
├── Is it event-driven, < 15 min execution?
│ └── YES → Lambda
│
├── Is it a simple web app/API needing fastest deployment?
│ └── YES → App Runner
│
├── Does your team know Kubernetes?
│ ├── YES + need multi-cloud/CNCF ecosystem → EKS
│ └── NO → ECS
│
├── Want to manage servers?
│ ├── NO → Fargate (with ECS or EKS)
│ └── YES (cost/GPU/custom needs) → EC2 (with ECS or EKS)
│
└── Need GPU, bare-metal, or kernel access?
└── YES → EC2 (raw or with ECS)
Cost Comparison: Same Workload, Different Compute
Workload: Web API, 2 vCPU, 4GB RAM, running 24/7, steady traffic
| Compute | Monthly Cost | Notes |
|---|---|---|
| EC2 (m7g.large, On-Demand) | ~$60 | You manage everything |
| EC2 (m7g.large, 1yr Savings Plan) | ~$38 | 37% savings, committed |
| ECS + Fargate (2 vCPU, 4GB) | ~$120 | No server management |
| EKS + Fargate (2 vCPU, 4GB) | ~$193 | $73 control plane + Fargate |
| EKS + EC2 (m7g.large) | ~$133 | $73 control plane + EC2 |
| App Runner (2 vCPU, 4GB) | ~$100 | Simplest path |
| Lambda (if 1M req/month) | ~$1 | Only if workload fits event model |
Takeaway: Lambda is cheapest for bursty workloads. EC2 with Savings Plans is cheapest for steady-state. Fargate/App Runner trade cost for operational simplicity.
Migration Paths
| From | To | When |
|---|---|---|
| EC2 → Fargate | You're spending too much time on instance management and patching | |
| Lambda → Fargate | Functions hitting 15-min timeout or cold starts are unacceptable | |
| ECS → EKS | Team growing, need CNCF tools, or multi-cloud is on the roadmap | |
| EKS → ECS | Over-engineered; small team drowning in Kubernetes complexity | |
| Fargate → EC2 | Scale reached where Fargate premium exceeds ops savings | |
| Monolith EC2 → ECS/EKS | Decomposing into microservices, need orchestration |
Summary
There's no "best" AWS compute service — only the best fit for YOUR workload:
- Lambda — event-driven, bursty, < 15 min. Cheapest at low scale.
- App Runner — simplest container deployment. Zero AWS knowledge needed.
- ECS + Fargate — standard container workloads, AWS-native, low ops. Sweet spot for most teams.
- EKS — Kubernetes ecosystem, multi-cloud, 15+ services. Higher complexity, more power.
- EC2 — full control, GPU, specialized instances. Cheapest at high steady-state utilization.
Choose based on: team skills, workload characteristics, scale, and how much operational overhead you're willing to accept. When in doubt, start with Fargate — you can always move to EC2 underneath later without changing application code.
Alpesh Kumbhare is an AWS Architect at Atos, specializing in AWS infrastructure automation and cloud architecture decisions. Connect on LinkedIn.
Top comments (0)