EC2 vs ECS vs Lambda: Choosing the Right Compute on AWS
Every AWS project starts with the same question: where should this code actually run? I've shipped production workloads on EC2, ECS, and Lambda, and the honest answer is that all three are the right choice, just for different shapes of work. The mistake is picking based on familiarity or hype instead of the workload. Here's the decision framework I use.
Start with the workload shape, not the service
Before comparing services, answer three questions about the workload itself:
- Traffic pattern. Is it steady all day, spiky around events, or mostly idle with occasional bursts? Steady favours reserved capacity; spiky and idle favour pay-per-use.
- Execution time. Requests measured in milliseconds, jobs measured in minutes, or processes that never stop? Lambda caps out at 15 minutes, so long-running work is disqualified immediately.
- State and dependencies. Does it need a local filesystem, a persistent connection pool, a specific runtime, or a GPU? The more it depends on its environment, the closer you stay to a real server.
When EC2 is the right answer
EC2 gets dismissed as "legacy" far too quickly. It's still the right call when you need full control of the OS, when software wasn't built for containers, or when the workload runs hot 24/7: a steady high-utilisation service on a reserved instance is often the cheapest option of the three. The price you pay is operational: patching, AMI management, capacity planning, and autoscaling configuration are all yours. If you're a small team, that overhead is real and recurring.
When ECS earns its place
ECS (especially with Fargate) is my default for web APIs and microservices. You get the deployment consistency of containers (the same image runs in CI, staging, and production) without managing hosts. For the multi-service Laravel platform I worked on, ECS hit the sweet spot: services that run continuously, need predictable latency, and deploy several times a week. Rolling deployments, service discovery, and load balancer integration come essentially free. The cost model sits between EC2 and Lambda: you pay for provisioned task capacity, not per request, so mostly-idle services still cost money.
When Lambda wins
Lambda is unbeatable for event-driven and bursty work: processing uploads from S3, reacting to queue messages, scheduled jobs, webhooks, and APIs with unpredictable or low traffic. Scale-to-zero means an endpoint that gets ten requests a day costs effectively nothing. The trade-offs are cold starts (manageable, but real for latency-sensitive APIs), the 15-minute limit, and an execution model that punishes anything needing persistent connections; database connection pooling on Lambda requires RDS Proxy or careful design.
My shortcut table
- Steady 24/7 service, high utilisation: EC2 with reserved instances.
- Containerised services, frequent deploys, predictable latency: ECS on Fargate.
- Event-driven, bursty, or low-traffic workloads: Lambda.
- Genuinely unsure: start with Lambda or Fargate. It's far easier to move from serverless to servers when traffic justifies it than to claw back the ops time you spent managing instances you didn't need.
The meta-lesson: compute choice is a cost-and-operations decision dressed up as a technical one. Pick the service whose trade-offs your team can actually afford to live with, and revisit the decision when the traffic pattern changes, because it will.