AWS Compute Services: How Do You Choose Between EC2, ECS, EKS, and Lambda?
From renting a VM to not thinking about servers at all — a walkthrough of EC2, ECS, EKS, and Lambda, what makes each one different, and how to pick the right one.
Why does AWS have so many ways to just "run code"?
Open the AWS console and the list of compute services alone is long: EC2, ECS, EKS, Lambda, plus Elastic Beanstalk, Lightsail, and more. If this is your first time here, you've probably hit the same wall everyone hits: I just want to run my program — why do I have to choose between all these services first?
Here's the thing: these services are really the same idea at different levels of abstraction. The lower you go, the more you manage yourself, but the more control you get. The higher you go, the more AWS handles for you, freeing you up to focus on business logic. This post climbs the ladder in order — EC2 → ECS → EKS → Lambda — and at each step you'll see it's solving a pain point the previous layer left behind.
The lowest layer: EC2, a computer that's entirely yours
EC2 (Elastic Compute Cloud) is AWS's most basic, most literal compute service — it's just a virtual machine. Pick your CPU, memory, and OS, AWS spins up a machine, and everything after that — what software to install, which ports to open, how to deploy your app — is entirely up to you.
Think of EC2 like renting an apartment: the landlord (AWS) handles the utilities and the foundation, but what furniture goes where, and how you divide up the rooms, is entirely on you. The upside is maximum control — you can install any custom software, tweak any system parameter you want. The downside is just as obvious: OS updates, security patches, scaling up when traffic spikes, restarting the thing when it crashes — all of that is on you too.
# Launching an EC2 instance via the AWS CLI — conceptually, renting an empty machine
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-keyOnce a team grows, just maintaining deployment scripts, health checks, and auto-scaling configs for a fleet of EC2 instances becomes a job in itself. That's what led to the next layer: handing off "how does my code actually run on a machine" to containers.
Packing your app into a shipping container: what is ECS?
Before getting into ECS, it helps to talk about containers. A container is basically a standardized shipping container — it doesn't matter what app is inside or which library versions it depends on, the container's shape and interface stay the same. The machine just needs to know how to move containers around; it doesn't need to care what's inside them.
ECS (Elastic Container Service) is AWS's own container orchestration system. You package your app as an image, and ECS decides which machines those containers run on, whether to restart them if they crash, and how to route traffic to them. Compared to managing a pile of EC2 instances by hand, you no longer need to SSH into every box to deploy — you just tell ECS "run N copies of this container" and let it handle the scheduling.
One catch: by default, ECS still needs a fleet of EC2 instances underneath as the actual chassis the containers run on — that fleet is called a cluster. In other words, you've upgraded from "managing how code runs" to "managing where containers run," but you're still on the hook for the machines themselves.
Fargate: making ECS even more "serverless"
What if you don't want to manage the underlying machines either? That's exactly what Fargate is for. Fargate is a launch type for ECS (and EKS, covered below, can use the same idea) that lets you skip creating or managing any EC2 instances at all — you just declare how much CPU and memory your container needs, and AWS provisions the compute behind the scenes to run it.
Stretching the apartment analogy further: EC2 is renting an empty unit and decorating it yourself. ECS on EC2 is hiring someone to manage tenant assignments across a building you still have to rent. Fargate is just staying at a hotel — you pay for the space and time you use, and you never have to think about the building itself.
Want industry-standard container orchestration? Enter EKS
ECS works well, but it's AWS's own proprietary scheduler, with its own configuration style and terminology. If your team already knows Kubernetes — the industry-standard container orchestrator — or you want the flexibility to move to another cloud someday without rebuilding everything from scratch, that's when you reach for EKS (Elastic Kubernetes Service).
EKS is essentially AWS managing the Kubernetes control plane for you — the most complex, highest-availability-critical part of Kubernetes, sometimes called its "brain." You don't have to stand up or maintain core components like the API server or etcd yourself; you just focus on defining native Kubernetes resources like Pods, Deployments, and Services. Like ECS, the worker nodes under EKS can be regular EC2 instances or, again, Fargate, if you'd rather not manage machines at all.
The short version: ECS is AWS's own design, most deeply integrated with the AWS ecosystem; EKS brings the industry-standard Kubernetes into AWS, trading a steeper learning curve for better portability across clouds.
Not managing servers at all: Lambda's serverless world
However much you simplify the first three services, there's still a "machine" somewhere in the picture — the only question is who manages it. Lambda removes that concept entirely. You don't manage machines, and you don't manage how many containers are running — you just upload a function, set up a trigger (an API call, a new file landing in S3, a schedule), and AWS provisions compute the moment the event fires, then tears it down the instant execution finishes.
This model is called serverless, and it changes how you pay too. With EC2, the meter runs as long as the machine is on. With Lambda, you pay only for actual execution time — no event, no invocation, no cost. It's a great fit for unpredictable traffic, or for anything that boils down to "do one small thing when an event happens" — generating a thumbnail after an image upload, handling the backend logic behind an API request, that sort of thing.
// A Lambda function handling an event from API Gateway
export const handler = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Someone called me!' }),
}
}The trade-off is minimal control: the execution environment, time limit, and memory size are all dictated by AWS, and it's a poor fit for long-running or stateful processes — Lambda has a hard cap of 15 minutes per invocation.
So how do you actually choose?
Lining up all four services on the same axis makes it much clearer:
| Service | What you manage | Best for |
|---|---|---|
| EC2 | OS, deployment, scaling, patching | Fully custom environments, lifting-and-shifting legacy apps |
| ECS | Container definitions; machines optional via Fargate | Staying inside the AWS ecosystem, simple container orchestration |
| EKS | Container definitions + Kubernetes resources | Cross-cloud flexibility, teams already on Kubernetes |
| Lambda | Just the function logic | Event-driven workloads, unpredictable traffic, short-lived tasks |
The core logic behind picking one boils down to a single sentence: how much control are you willing to give up in exchange for AWS taking on more of the operational work? The more control you want, the more operational responsibility you carry; the closer you move toward serverless, the lighter that burden gets — but so does your flexibility and room for customization. In practice, most systems don't pick just one — it's common to run core services on ECS or EKS while handling scattered event triggers with a few Lambda functions on the side.
Wrapping up
EC2, ECS, EKS, and Lambda aren't competing products — they're different stops on the same spectrum of abstraction. EC2 gives you maximum control and the heaviest operational load. ECS simplifies deployment through containerization and AWS-native orchestration. EKS trades a steeper learning curve for the portability of industry-standard Kubernetes. And Lambda removes the concept of a server altogether, so all you have to think about is your code.