AWS gives you three ways to run your code in the cloud:
- Lambda - upload a function, AWS runs it when events happen
- ECS (Elastic Container Service) - run Docker containers, AWS manages the servers
- EKS (Elastic Kubernetes Service) - run Kubernetes, AWS manages the control plane
All three are production-ready. All three scale. All three integrate with every other AWS service. And all three are a perfectly valid answer to "where should I deploy my web app?"
So which one do you choose?
After deploying across all three (and building TurboDeploy on top of ECS), here's the honest comparison we wish existed when we started.
The Quick Answer
If you're too busy to read the full post:
| Your Situation | Use This |
|---|---|
| Event-driven functions, cron jobs, webhooks | Lambda |
| Web apps, APIs, microservices (most startups) | ECS Fargate ⭐ |
| Large org with a dedicated platform team + multi-cloud needs | EKS |
| Not sure | ECS Fargate (you can always migrate later) |
Now let's look at why.
AWS Lambda - The Event Machine
What It Is
Lambda runs your code in response to events without you managing any servers. You upload a function (a zip file or container image), configure a trigger (HTTP request, S3 upload, SQS message, cron), and AWS handles everything else: provisioning, scaling, patching, and monitoring.
The Good
- Zero infrastructure management : no servers, no containers, no clusters
- Scales to zero : if nobody is using your app, you pay nothing
- Instant horizontal scaling : each request gets its own execution environment
- Generous free tier : 1 million requests + 400,000 GB-seconds per month, forever
- Sub-second billing : charged per millisecond of execution time
- Deep AWS integration : triggers from S3, DynamoDB, SQS, API Gateway, EventBridge
The Bad
- 15-minute maximum timeout : if your function runs longer, it gets killed. No exceptions.
- Cold starts : first invocation after idle takes 100ms–2s extra latency (runtime-dependent)
- Limited compute : max 10 GB memory, 6 vCPUs per function
- Stateless : no persistent local storage between invocations
- Vendor lock-in : Lambda functions are tightly coupled to AWS's event model
- INIT phase billing : since August 2025, AWS charges for the initialization phase too
-
Debugging is harder : no SSH, no
docker exec, limited local dev experience
Lambda Pricing (us-east-1)
| Component | Price |
|---|---|
| Requests | $0.20 per 1 million requests |
| Duration (128 MB) | $0.0000000021 per ms |
| Duration (1 GB) | $0.0000000167 per ms |
| Duration (10 GB) | $0.0000001667 per ms |
| Free tier | 1M requests + 400K GB-seconds/mo |
Real-world example: An API handling 5 million requests/month at 200ms avg, 512 MB memory:
Requests: 5M × $0.20/M = $1.00
Duration: 5M × 200ms × 0.5 GB × $0.0000000083/ms = $4.15
Monthly total: ~$5.15
Lambda is remarkably cheap at low-to-moderate volume.
When Lambda Breaks Down
Lambda's economics flip at high, steady traffic. The same workload at 50 million requests/month:
Requests: 50M × $0.20/M = $10.00
Duration: 50M × 200ms × 0.5 GB × $0.0000000083/ms = $41.50
Monthly total: ~$51.50
Meanwhile, an ECS Fargate task running 24/7 at 1 vCPU / 2 GB could handle that same throughput for ~$43/mo and without cold starts.
The rule: Lambda is cheapest for bursty, low-volume traffic. For steady 24/7 workloads, containers win.
Best Use Cases for Lambda
| Use Case | Example |
|---|---|
| API backends with variable traffic | REST/GraphQL API via API Gateway |
| File processing | Resize images when uploaded to S3 |
| Event processing | Process SQS messages, DynamoDB streams |
| Cron jobs | Run a task every hour via EventBridge |
| Webhooks | Receive and process Stripe/GitHub webhooks |
| Data pipelines | Transform data between services |
Amazon ECS Fargate: The Middle Ground
What It Is
ECS (Elastic Container Service) runs Docker containers on AWS. With Fargate as the launch type, you don't manage any EC2 instances, you define your container, specify how much CPU and memory it needs, and AWS handles the rest.
Think of it as: "Docker containers as a managed service."
The Good
- No servers to manage - Fargate provisions and manages the compute
- No control plane fee - ECS itself is free (you only pay for Fargate compute)
- Full Docker support - run any container (any language, any framework)
- Always warm - no cold starts; your containers are running 24/7 (or auto-scaled)
- No timeout limits - run processes for hours, days, months
- Deep AWS integration - ALB, CloudWatch, IAM, Secrets Manager, all native
- Auto-scaling - scale based on CPU, memory, request count, or custom metrics
- Simpler than Kubernetes - task definitions instead of YAML manifests
The Bad
- Doesn't scale to zero - minimum 1 task always running (you pay even if idle)
- Slower scale-up - new Fargate tasks take 30–60 seconds to provision
- AWS-specific - ECS APIs are not Kubernetes-compatible (not portable)
- Still requires some ops knowledge - task definitions, networking, ALB configuration
- No built-in CI/CD - you bring your own deployment pipeline
ECS Fargate Pricing (us-east-1)
| Resource | Price per Hour | Price per Month (24/7) |
|---|---|---|
| 0.25 vCPU | $0.01012 | ~$7.40 |
| 0.5 vCPU | $0.02024 | ~$14.80 |
| 1 vCPU | $0.04048 | ~$29.50 |
| 2 vCPU | $0.08096 | ~$59.10 |
| 1 GB Memory | $0.00445 | ~$3.25 |
| 2 GB Memory | $0.00890 | ~$6.50 |
| 4 GB Memory | $0.01780 | ~$13.00 |
Real-world example: A typical web app (1 vCPU, 2 GB RAM, running 24/7):
Compute: $29.50 (vCPU) + $6.50 (RAM) = $36.00/mo
ALB: ~$22/mo (load balancer + LCU)
Total: ~$58/mo for a production-grade deployment
With Compute Savings Plans (1-year commit): ~$25/mo for compute which is a 30% discount.
What Makes ECS the Default for Web Apps
| Feature | Why It Matters for Web Developers |
|---|---|
| No cold starts | Every request hits a warm container instantly |
| No timeout | WebSockets, long-running jobs, streaming - all work |
| Docker-native | Use your existing Dockerfile, no changes needed |
| ALB integration | HTTPS, path routing, health checks - all built in |
taskRoleArn |
Fine-grained IAM per service |
| CloudWatch Logs | Built-in logging, no add-ons needed |
| Auto-scaling | Scale on CPU, memory, or custom metrics |
| Express Mode | New simplified deployment option |
Best Use Cases for ECS
| Use Case | Example |
|---|---|
| Web applications | Express, Next.js, Django, Rails, FastAPI |
| REST/GraphQL APIs | Production APIs with consistent traffic |
| Background workers | SQS consumers, job processors |
| Microservices | Multiple services with service discovery |
| WebSocket servers | Real-time applications (chat, notifications) |
| Scheduled tasks | Cron via EventBridge → ECS RunTask |
Amazon EKS: Full Kubernetes on AWS
What It Is
EKS (Elastic Kubernetes Service) runs a managed Kubernetes control plane on AWS. You define your workloads using standard Kubernetes manifests (YAML), and EKS manages the master nodes, the API server, and etcd. You bring the worker nodes (EC2 or Fargate).
The Good
- Standard Kubernetes - same API as on-prem, GKE, AKS; truly portable
- Massive ecosystem - Helm, ArgoCD, Istio, KEDA, Prometheus, Operators - all work
- Maximum flexibility - custom schedulers, sidecars, init containers, service mesh
- Multi-cluster/multi-region - sophisticated deployment topologies
- Strong community - Kubernetes is the standard for container orchestration at this point
- Granular scaling - HPA (Horizontal Pod Autoscaler), VPA (Vertical), KEDA (event-driven)
- Infrastructure as Code - fully Terraform/Pulumi/CDK compatible
The Bad
- $73/month just for the control plane - before you run a single container. Per cluster.
- Steep learning curve - Pods, Deployments, Services, Ingress, RBAC, ConfigMaps, Secrets, Namespaces, Operators. It's a LOT of concepts.
- "YAML hell" - even a simple deployment requires 100+ lines of YAML manifests
- Operational overhead - cluster upgrades, node group management, add-on compatibility
- Requires dedicated expertise - realistically, you need someone on the team who knows Kubernetes
- Slow to iterate on - more moving parts = more things to debug
- Overkill for most startups - you're paying the "Kubernetes tax" in both money and engineering time
EKS Pricing (us-east-1)
| Component | Price |
|---|---|
| EKS Control Plane | $0.10/hour = $73/month per cluster |
| EKS Extended Support | $0.60/hour (older K8s versions) |
| Worker Nodes (Fargate) | Same Fargate pricing as ECS |
| Worker Nodes (EC2) | Standard EC2 pricing |
Real-world example: Same web app (1 vCPU, 2 GB RAM) on EKS with Fargate:
Control plane: $73.00/mo (unavoidable)
Compute: $36.00/mo (same Fargate pricing as ECS)
ALB/Ingress: ~$22/mo
Total: ~$131/mo
That's $73/month more than ECS for the exact same workload. The Kubernetes control plane is a fixed tax.
The "Team Size" Rule
Here's the uncomfortable truth about EKS:
| Team Size | Recommendation | Reason |
|---|---|---|
| 1–3 engineers | ❌ Avoid EKS | You don't have bandwidth for Kubernetes ops |
| 3–10 engineers | 🟡 Probably not | ECS gives you 90% of the value at 10% of the complexity |
| 10–30 engineers | 🟡 Consider EKS | If you have a dedicated platform/DevOps engineer |
| 30+ engineers | ✅ EKS makes sense | Dedicated platform team, complex multi-service architecture |
The exception: If your team already knows Kubernetes deeply (ex-Google, ex-large-enterprise), EKS is fine at any team size. The problem isn't Kubernetes itself, it's the learning curve when your team doesn't have the expertise.
Best Use Cases for EKS
| Use Case | Example |
|---|---|
| Multi-cloud/hybrid | Same manifests on AWS, GCP, Azure |
| Platform engineering | Internal developer platform with custom tooling |
| Complex microservices | 50+ services with service mesh (Istio/Linkerd) |
| ML/AI workloads | Custom GPU scheduling, Kubeflow, Ray |
| Regulated industries | Kubernetes-native policy engines (OPA/Gatekeeper) |
| Migrating from on-prem K8s | Already running Kubernetes, moving to cloud |
Head-to-Head Comparison
Architecture & Deployment
| Lambda | ECS Fargate | EKS | |
|---|---|---|---|
| Deploy unit | Function (zip/container) | Docker container | Kubernetes Pod |
| Deploy command | aws lambda update-function-code |
aws ecs update-service |
kubectl apply -f |
| Config format | Function configuration | Task Definition (JSON) | K8s Manifests (YAML) |
| Lines of config | ~20 | ~50 | ~150+ |
| Time to first deploy | 5 minutes | 30 minutes | 2+ hours |
| CI/CD | SAM, CDK, Serverless Framework | GitHub Actions + ECR | ArgoCD, Flux, Helm |
Scaling
| Lambda | ECS Fargate | EKS | |
|---|---|---|---|
| Scale to zero | ✅ Yes | ❌ No (min 1 task) | ❌ No (unless using KEDA) |
| Scale-up speed | Instant (ms) | 30–60 seconds | 30–60 seconds |
| Max scale | 1,000 concurrent (soft limit) | Thousands of tasks | Thousands of pods |
| Scaling trigger | Automatic (per-request) | CPU/Memory/ALB metrics | HPA, VPA, KEDA |
| Burst handling | Excellent | Good (with pre-scaling) | Good (with pre-scaling) |
Networking
| Lambda | ECS Fargate | EKS | |
|---|---|---|---|
| Load balancer | API Gateway | Application Load Balancer | ALB Ingress Controller |
| Custom domain | API Gateway + ACM | ALB + Route 53 + ACM | Ingress + cert-manager |
| VPC support | Optional (adds latency) | Native | Native |
| Service discovery | ❌ | Cloud Map | Kubernetes DNS |
| Service mesh | ❌ | App Mesh (limited) | Istio, Linkerd (full) |
Observability
| Lambda | ECS Fargate | EKS | |
|---|---|---|---|
| Logs | CloudWatch (automatic) | CloudWatch (automatic) | CloudWatch or Fluentd |
| Metrics | CloudWatch + X-Ray | CloudWatch + Container Insights | Prometheus + Grafana |
| Tracing | X-Ray (built-in) | X-Ray | Jaeger, X-Ray, or Zipkin |
| Dashboards | Limited | Container Insights | Grafana (full customization) |
The Cost Breakdown (Real Numbers)
Scenario 1: Low-Traffic API (1M requests/month)
| Lambda | ECS Fargate | EKS | |
|---|---|---|---|
| Compute | $5 | $36 | $36 |
| Control plane | $0 | $0 | $73 |
| Load balancer | $4 (API GW) | $22 (ALB) | $22 (ALB) |
| Monthly | $9 | $58 | $131 |
Winner: Lambda. For low-traffic, bursty APIs, nothing beats it on price.
Scenario 2: Steady-Traffic SaaS App (10M requests/month)
| Lambda | ECS Fargate | EKS | |
|---|---|---|---|
| Compute | $52 | $36 | $36 |
| Control plane | $0 | $0 | $73 |
| Load balancer | $15 (API GW) | $22 (ALB) | $22 (ALB) |
| Monthly | $67 | $58 | $131 |
Winner: ECS Fargate : Lambda's per-request pricing catches up and ECS has no cold starts.
Scenario 3: High-Traffic Platform (100M requests/month)
| Lambda | ECS Fargate (2 vCPU) | EKS (2 vCPU) | |
|---|---|---|---|
| Compute | $415 | $72 | $72 |
| Control plane | $0 | $0 | $73 |
| Load balancer | $45 (API GW) | $25 (ALB) | $25 (ALB) |
| Monthly | $460 | $97 | $170 |
Winner: ECS Fargate : Lambda is 4.7x more expensive. The "pay per request" model punishes high-volume workloads.
Scenario 4: The Hybrid Approach
Most mature architectures combine services:
Core API (steady traffic) → ECS Fargate ($58/mo)
Image processing (S3 triggers) → Lambda ($3/mo)
Nightly data export (cron) → Lambda ($0.50/mo)
Background email sending (SQS) → Lambda ($1/mo)
Total: $62.50/mo
You get always-warm containers for latency-sensitive APIs and scale-to-zero functions for event-driven tasks. Best of both.
The Hidden Cost: Engineering Time
Pricing isn't just about AWS bills. There's an engineering cost too:
| Service | Time to First Deploy | Ongoing Ops per Month | Debugging Difficulty |
|---|---|---|---|
| Lambda | 30 minutes | ~2 hours | Medium (CloudWatch + X-Ray) |
| ECS Fargate | 2–4 hours | ~4 hours | Easy (docker exec, CloudWatch) |
| EKS | 1–2 days | ~20+ hours | Hard (kubectl, k8s events, logs) |
If your engineering team costs $150/hour, the EKS operational overhead (~20 hrs/mo extra) is an additional $3,000/month in engineering time. That's the real "Kubernetes tax."
When to Migrate Between Services
Lambda → ECS (Most Common Migration Path)
Signs it's time:
- Your Lambda bill exceeds your projected Fargate cost
- You're hitting the 15-minute timeout
- Cold starts are impacting user experience
- You need WebSocket connections
- You need persistent local state or large memory
Migration effort: Medium (1–2 weeks). You need to:
- Containerize your app
- Deploy to ECS
- Update your API Gateway to point to the ALB (or replace with ALB)
ECS → EKS (Less Common, Higher Stakes)
Signs it's time:
- You need multi-cloud portability (running on AWS + GCP/Azure)
- You have 50+ microservices and need a service mesh
- Your team has deep Kubernetes expertise
- You're investing in a full internal developer platform
- Compliance requires Kubernetes-native policy engines
Migration effort: High (1–3 months). You need to:
- Convert ECS task definitions to Kubernetes Deployments/Services
- Replace ALB with Ingress controller
- Set up cluster monitoring (Prometheus/Grafana)
- Train the team on Kubernetes operations
Our honest opinion: If you're considering ECS → EKS, first ask: "Is there a specific Kubernetes feature I need that ECS doesn't provide?" If the answer is vague ("flexibility" or "it's the industry standard"), you probably don't need EKS yet.
The Decision Framework
Choose Lambda If:
- ✅ Tasks are event-driven (S3 triggers, SQS, webhooks)
- ✅ Execution time is under 15 minutes
- ✅ Traffic is bursty or unpredictable
- ✅ You want zero ops burden
- ✅ Monthly request volume is under 10 million
- ❌ NOT for: WebSockets, long-running processes, high-volume steady APIs
Choose ECS Fargate If:
- ✅ You're building a web app, API, or microservice
- ✅ Traffic is steady or predictable
- ✅ You need no timeout limits
- ✅ Your team is 1–15 engineers
- ✅ You want AWS-native simplicity
- ✅ You're coming from Heroku/Railway/Render
- ❌ NOT for: Event-driven functions (use Lambda) or complex multi-cloud K8s
Choose EKS If:
- ✅ You require Kubernetes-specific features (operators, CRDs, service mesh)
- ✅ You have a dedicated platform/DevOps team
- ✅ You need multi-cloud portability
- ✅ You're running 30+ microservices at scale
- ✅ You're migrating from on-prem Kubernetes
- ❌ NOT for: Small teams, simple web apps, cost-sensitive startups
What We Chose (And Why)
At TurboDeploy, we deploy your apps on ECS Fargate. Here's why:
- No control plane cost : ECS is free. The $73/mo EKS tax can't be justified for our users' workloads.
-
Simpler is better : our startup users don't need Kubernetes. They need
git push → running app. - Docker-native : a Dockerfile is all you need. No YAML manifests, no Helm charts, no operators.
- Full AWS integration : ALB, HTTPS, IAM roles, auto-scaling, CloudWatch - all "just work" with ECS.
- Migration path exists : if a user outgrows ECS, migrating to EKS is straightforward because the Docker images are the same.
We use Lambda for internal automation (webhook processing, cron cleanup tasks, notification delivery) where scale-to-zero makes sense.
We don't use EKS. Not because it's bad but because it solves problems we (and most of our users) don't have.
TL;DR
| Lambda | ECS Fargate | EKS | |
|---|---|---|---|
| One-liner | Functions for events | Containers for apps | Kubernetes for scale |
| Control plane cost | $0 | $0 | $73/mo per cluster |
| Cold starts | Yes (100ms–2s) | No | No |
| Max timeout | 15 minutes | None | None |
| Scale to zero | ✅ | ❌ | ❌ (without KEDA) |
| Learning curve | Low | Medium | Very High |
| Team requirement | Any | Any | Dedicated K8s engineer |
| Best for startups | Cron + events | Web apps ⭐ | Rarely |
| Vendor lock-in | High | Medium | Low (K8s is portable) |
| Our pick | Internal tasks | User deployments ⭐ | Not yet |
Don't want to think about compute choices? TurboDeploy deploys your app on ECS Fargate with ALB, HTTPS, auto-scaling, and monitoring set up for you. Connect your repo and go.



Top comments (0)