Skip to content
BytePatterns

ECS vs EKS vs Fargate: How to Choose Containers on AWS

9 min readBytePatterns

ECS vs EKS vs Fargate as two decisions: the orchestrator that runs your containers and the compute under it, and Fargate's limits on GPUs, daemons and networks.

"Should we use ECS, EKS or Fargate?" sounds like a choice between three products. It is not, and the most common mistake in an interview is to answer it as if it were. ECS and EKS are orchestrators: they decide where containers run and keep them running. Fargate is compute: somewhere for the containers to run without servers you manage. You pick one of each. Everything below comes from the AWS documentation pages listed at the end, as of September 2026.

The problem it solves

You have a container image and want it running on AWS, at a given number of copies, replaced when it dies, reachable behind a load balancer. That needs two things:

  • An orchestrator, which holds the desired state (run three copies of this image, with this much CPU and memory) and works to keep it true.
  • Capacity, the machines the containers actually run on.

The decision guide describes the same split as layers: a compute capacity layer (Amazon EC2, AWS Fargate, AWS Outposts) and an orchestration layer (Amazon ECS, Amazon EKS, and Red Hat OpenShift Service on AWS).

The intuition

ECS is AWS's own orchestrator. Its vocabulary is small: a task definition is the blueprint, a task is a running copy, a service keeps a number of tasks running for a long-lived application, and a cluster is the infrastructure they run on. There is no control plane for you to run or upgrade.

EKS is managed Kubernetes. AWS runs the Kubernetes control plane; you get the real Kubernetes API, its ecosystem of manifests, Helm charts and operators, and its learning curve. The decision guide adds a cost that is easy to forget: Kubernetes ships three releases a year and deprecates old versions, so teams must plan for frequent cluster upgrades.

Capacity is the second decision, and it applies to either orchestrator:

  • EC2 capacity: instances you choose, patch and scale. Full control, full responsibility. ECS also offers ECS Managed Instances, where the tasks still run on EC2 instance types but AWS handles provisioning, patching and scaling.
  • Fargate: serverless compute for both ECS and EKS. There are no instances to manage, and each task or pod runs in its own isolation boundary; on EKS, a pod on Fargate does not share its kernel, CPU, memory or network interface with another pod.

What Fargate gives up is what an interviewer will probe:

  • No GPUs. GPU work needs EC2 capacity, under either orchestrator.
  • No privileged containers. On EKS, also no DaemonSets and no HostPort or HostNetwork; a daemon becomes a sidecar container in each pod.
  • Sizes come from a fixed menu. On ECS you set CPU and memory at the task level from supported pairs; 0.25 vCPU allows 0.5, 1 or 2 GB, and 1 vCPU allows 2 to 8 GB.
  • Networking is per task. ECS tasks on Fargate always use the awsvpc mode, so each task gets its own elastic network interface and security groups. A task in a private subnet needs a NAT gateway, or an interface VPC endpoint for Amazon ECR, to pull its image. On EKS, Fargate pods run only in private subnets, and load balancers must use IP targets.
  • Storage is limited on EKS. Amazon EBS volumes cannot be mounted to Fargate pods; Amazon EFS can, with static provisioning.

Watch it run

The animation lays out the two questions as a grid, orchestrators on top and capacity underneath, and introduces each box in turn. Then three briefs arrive. A four-person team, all-in on AWS, running a stateless web API, lands on ECS on Fargate: the fewest moving parts, and nobody patches a host. A platform team that already runs Kubernetes elsewhere lands on EKS, to keep the same manifests and tooling. A GPU inference service needs EC2 capacity, under either orchestrator, because Fargate does not offer GPUs. The last frame is the interview answer: name both choices and why.

ECS vs EKS vs Fargate

Step 1 of 10

It is two questions, not one: who orchestrates the containers, and what compute they run on.

The same interactive animation as the lesson — step through it with the controls.

The code

The lesson's service, created from the AWS CLI:

# illustrative: cluster, subnets and security group are placeholders
aws ecs create-service --cluster prod --service-name api \
  --task-definition api:7 --desired-count 3 --launch-type FARGATE \
  --network-configuration \
  "awsvpcConfiguration={subnets=[subnet-a,subnet-b],securityGroups=[sg-api]}"

A toy model of the decision, not an AWS tool: the facts above as rules, with a simple preference for owning less:

def choose(k8s_team=False, gpu=False, privileged=False, daemons=False):
    """Toy model of the two decisions, as documented in September 2026."""
    orchestrator = "EKS" if k8s_team else "ECS"      # the API the team already knows
    fargate_ok = not (gpu or privileged or (daemons and orchestrator == "EKS"))
    return orchestrator, "Fargate" if fargate_ok else "EC2 capacity"

print(choose())                                # ('ECS', 'Fargate')
print(choose(k8s_team=True))                   # ('EKS', 'Fargate')
print(choose(gpu=True))                        # ('ECS', 'EC2 capacity')
print(choose(k8s_team=True, daemons=True))     # ('EKS', 'EC2 capacity')

Another toy model: the documented Fargate task sizes for Linux on ECS, up to 4 vCPU (larger sizes exist), as a check you could run before registering a task definition:

FARGATE_SIZES = {                              # CPU units -> allowed memory in GB
    256: [0.5, 1, 2],
    512: [1, 2, 3, 4],
    1024: list(range(2, 9)),
    2048: list(range(4, 17)),
    4096: list(range(8, 31)),
}

def valid_task_size(cpu_units, memory_gb):
    return memory_gb in FARGATE_SIZES.get(cpu_units, [])

print(valid_task_size(256, 0.5), valid_task_size(256, 4))   # True False
print(valid_task_size(1024, 8), valid_task_size(3000, 8))   # True False

The rules checked against an exhaustive search: for every combination of needs, list all four orchestrator and capacity pairs, drop the ones the documentation rules out, and keep the one with the least to operate:

from itertools import product

def exhaustive(k8s_team, gpu, privileged, daemons):
    candidates = []
    for orch, compute in product(["ECS", "EKS"], ["Fargate", "EC2 capacity"]):
        if k8s_team and orch != "EKS":
            continue                           # the team's manifests need Kubernetes
        if compute == "Fargate" and (gpu or privileged):
            continue                           # not offered on Fargate
        if compute == "Fargate" and orch == "EKS" and daemons:
            continue                           # no DaemonSets on Fargate
        burden = (orch == "EKS") + (compute == "EC2 capacity")
        candidates.append((burden, orch, compute))
    return min(candidates)[1:]

print(all(choose(*needs) == exhaustive(*needs)
          for needs in product([False, True], repeat=4)))   # True

The complexity

The costs here are operational, not asymptotic:

  • ECS on Fargate has the fewest things to own: no control plane, no hosts. It is also the most AWS-specific.
  • EKS adds a Kubernetes cluster to upgrade and a larger surface to learn, in exchange for the Kubernetes API and portability of skills and manifests.
  • EC2 capacity adds host patching, scaling and packing, in exchange for GPUs, privileged workloads and control over instance types.

Where it goes wrong

  • Calling Fargate an orchestrator. It is compute; ECS or EKS still schedules the work.
  • Planning a GPU service on Fargate. It is not offered; use EC2 capacity.
  • Private subnets with no route for image pulls. Fargate tasks then fail to start; add a NAT gateway or an ECR interface endpoint.
  • An EKS pod that matches no Fargate profile. It can sit Pending; the profile must match when the pod is scheduled.

When it shows up in interviews

It shows up in AWS, platform and system design interviews, usually as a brief: "a small team, a stateless API, what do you run it on?" or "your ML service needs GPUs". The follow-ups test the split: can Fargate run under EKS (yes), why pick EKS (the team already runs Kubernetes), and what Fargate cannot do.

How to say it in an interview

"It is two choices. The orchestrator is ECS, AWS's own and simpler, or EKS, which is managed Kubernetes and worth it if the team already runs Kubernetes. The compute is EC2 capacity, which I patch and scale, or Fargate, where each task or pod runs in its own boundary and there are no hosts. For a small team with a stateless API I would pick ECS on Fargate. Fargate has no GPUs and no privileged containers, and on EKS no DaemonSets, so those workloads go on EC2 capacity."

Scaling the EC2 side is covered in EC2 Auto Scaling explained, and the Kubernetes side in Kubernetes requests, limits and the HPA. Other AWS questions in this area are collected in AWS architecture interview questions.

Sources