open atlas
↑ Back to track
AWS, hands-on AWS · 02 · 01

Compute options: EC2, ECS/Fargate, Lambda, App Runner

AWS compute is a spectrum from most-control/most-ops to least — EC2, ECS-on-EC2, Fargate, Lambda, App Runner. Pick by workload shape, not by hype, and price in the traps each tier hides.

AWS Middle ◷ 18 min
Level
FoundationsJuniorMiddleSenior

A team ships an image-thumbnailing service on Lambda because “serverless is cheaper.” It works beautifully for six months — until a marketing push floods uploads, a handful of 4K source images push processing past 15 minutes, and the function starts timing out mid-job with no partial result. Worse, the functions live in a VPC to reach a private database, so each cold start now also waits on an elastic network interface to attach. The fix wasn’t tuning Lambda harder. It was admitting the workload had outgrown the tier — long-running, heavy, steady — and moving it to a Fargate task. Choosing compute is choosing constraints, and the constraints are not optional.

The spectrum: control versus operational burden

Every AWS compute option sits on a single axis. At one end is EC2 — raw virtual machines. You get a full operating system, root access, any instance type including GPU and bare-metal, and total control. The price of that control is that you own everything above the hypervisor: OS patching, the autoscaling group, load-balancer wiring, capacity planning, and the on-call when a host degrades. EC2 is the floor that everything else is built on, and it never disappears — Fargate and Lambda are EC2 capacity that AWS operates for you.

One step in is ECS on EC2: you still run and pay for the EC2 instances (the “container hosts”), but ECS schedules your containers onto them. You’ve handed off container orchestration and kept node management. Move one step further and the nodes vanish: ECS or EKS on Fargate is serverless containers. There is no instance to patch, scale, or right-size — you declare a task’s vCPU and memory, AWS finds capacity, and you pay per task for the time it runs. You give up host access (no SSH, no daemonset, no GPU) in exchange for never thinking about a node again.

Further still is Lambda: you don’t even ship a container host or a long-running process — you ship a function. AWS runs it in response to an event (an HTTP request via API Gateway, an S3 upload, an SQS message), scales it from zero to thousands of concurrent executions automatically, and bills you per millisecond of execution. The tradeoff is a hard shape: a 15-minute maximum execution time, cold starts when a new execution environment must spin up, and an event-driven programming model. At the far end is App Runner — point it at a container image or a source repo and it builds, deploys, load-balances, TLS-terminates, and autoscales a web service for you. It is the least to operate and the least flexible: a managed front for exactly one shape, the stateless HTTP service.

Four dimensions that decide the tier

Don’t compare these by name — compare them by behavior. Four dimensions separate them, and a workload’s answers point straight at the tier.

Operational model is who owns the OS and the fleet. EC2: you, entirely. ECS-on-EC2: you own hosts, AWS schedules containers. Fargate/Lambda/App Runner: AWS owns the host; you own only your code and its config.

Scaling model is how capacity follows load. EC2 scales by autoscaling group — you set policies, and new instances take minutes to boot and warm. Fargate scales tasks (still tens of seconds to start a task). Lambda scales by concurrent executions almost instantly and uniquely scales to zero — you pay nothing when idle. App Runner autoscales request-driven concurrency for you.

Pricing model follows the scaling. EC2 bills per running instance-hour whether or not it’s busy (on-demand, or far cheaper with Savings Plans / Spot). Fargate bills per task’s provisioned vCPU and memory for its lifetime. Lambda bills per request plus GB-seconds of actual execution, rounded to the millisecond — genuinely zero at idle. App Runner bills for provisioned + active compute.

Latency / cold-start behavior is the one teams forget. EC2 and steadily-running Fargate tasks have no per-request cold start — they’re already warm. Lambda pays a cold start (tens of ms for a light runtime, up to seconds for a heavy JVM/.NET or a large package) whenever it must create a new execution environment, and pays extra cold-start latency if the function is in a VPC and must attach an ENI. App Runner keeps a warm pool but can scale provisioned instances down, with its own spin-up on a cold path.

DimensionEC2FargateLambdaApp Runner
Ops burdenHighest — you patch the OSLow — no nodesLow — code onlyLowest — managed
ScalingASG, minutes to bootPer task, ~tens of secPer execution, near-instant, to zeroRequest-driven, managed
PricingPer instance-hour (Spot/SP cheaper)Per task vCPU + memoryPer request + GB-sec (zero idle)Provisioned + active compute
Cold startNone (warm fleet)None if runningYes — worse in VPC, worse for JVM/.NETWarm pool; spin-up on scale-up
Hard limitsNone (you own the box)No GPU, no host access15-min max, 10GB mem, no GPUHTTP web service only
Why this works

“Serverless” is not one thing. Fargate is serverless containers — you still provision vCPU/memory per task and the task runs continuously while it exists, so it has no per-request cold start but also never scales to zero on its own. Lambda is serverless functions — it scales to zero and bills per millisecond, but pays a cold start and caps at 15 minutes. They solve different problems: Fargate removes node management for steady or long-running work; Lambda removes idle cost for spiky or event-driven work. Reaching for “serverless” without saying which one usually means picking the wrong tradeoff.

Choosing by workload shape

Seniors don’t pick a favorite tier and bend workloads to it; they read the workload and let it choose. A few canonical shapes:

A steady, high-traffic service — a busy API handling thousands of requests per second around the clock — wants EC2 or Fargate. At constant high utilization, per-instance or per-task pricing beats per-request Lambda billing, and a warm fleet has no cold-start tax. Use EC2 when you need instance-level control or the cheapest steady compute via Spot/Savings Plans; use Fargate when you’d rather not manage nodes.

A spiky or event-driven workload — a webhook handler, an S3-triggered pipeline, a cron job, traffic that’s near-zero at night — wants Lambda. Scale-to-zero means you pay nothing in the troughs, and per-request scaling absorbs spikes that would force an autoscaling group to overprovision. Just keep each invocation short and stateless.

A simple containerized web app you don’t want to operate — an internal tool, a small product service, a side project that must not become an ops job — wants App Runner (or Fargate if you need more control). Push the image, get a URL, autoscaling and TLS included.

And anything needing OS-level control or GPUs — a service with kernel-tuning needs, a custom networking stack, ML inference or training on GPUs, software with bare-metal licensing — must use EC2. Fargate has no GPU and no host access, and Lambda has neither plus the 15-minute wall, so they are simply off the table.

Pick the best fit

A nightly batch job processes a queue of large media files; some single files take 25–40 minutes to transcode, and the queue is empty most of the day. Pick the compute.

Quiz

A workload runs continuously at high, near-constant traffic 24/7. Which billing model is most likely cheapest?

Quiz

Your Lambda functions sit in a VPC to reach a private RDS database and feel slow on the first request after idle. What's the most likely cause?

Recall before you leave
  1. 01
    Lay out the AWS compute spectrum from most control to least, and the single thing you trade at each step.
  2. 02
    Give the decision rule for matching a workload to a tier, with the canonical shapes and the traps.
Recap

AWS compute is a single spectrum from most control and most operations to least: EC2 gives you raw VMs and total control at the cost of owning the OS, scaling, and patching; ECS on EC2 hands off container scheduling but keeps node management; Fargate is serverless containers with no nodes to manage, billed per task vCPU and memory; Lambda is event-driven functions that scale to zero and bill per millisecond but cap at 15 minutes and pay cold starts; App Runner is a fully managed web service that’s the simplest to run and the least flexible. Choose by workload shape across four dimensions — operational model, scaling, pricing, and cold-start latency. Steady high traffic favors EC2 or Fargate; spiky or event-driven work favors Lambda’s scale-to-zero; a simple web app you don’t want to operate favors App Runner or Fargate; and anything needing GPUs or OS-level control forces EC2, because Fargate has no GPU or host access and Lambda adds the 15-minute wall and cold-start latency (made worse inside a VPC). The skill isn’t loving one tier — it’s reading the workload and accepting the constraints of the cheapest tier it actually fits. Now when you see a team reach for Lambda by default, your first question is: what is the duration, the traffic shape, and the OS access requirement? Those three answers pick the tier before a single line of infrastructure code is written.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 5 done
Connected lessons

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources4
expand
  1. 01
  2. 02
  3. 03
  4. 04

Trademarks belong to their respective owners. Editorial reference only.