Skip to content
Ayhan Sipahi Ayhan Sipahi

AWS Fargate 101: Serverless Containers Explained

A practical guide to AWS Fargate: task definitions, awsvpc networking, cost trade-offs, and when serverless containers beat managing EC2 hosts yourself.

Running containers on EC2 means managing OS patches, cluster capacity, and host-level failures. That work scales with the number of hosts, not with application complexity. AWS Fargate takes the layer away: you hand AWS a container image and a CPU/memory pair, and it runs the task on infrastructure you never log into.

For new containerized workloads, Fargate is the sensible default. You pay a premium per unit of compute and stop maintaining hosts in exchange. The cases where that trade goes the wrong way are specific: GPU workloads, privileged containers, and steady high utilization that Reserved Instances or Spot already cover. Knowing which side of that line a workload falls on is most of the decision.

How to Think About Fargate

In practice, Fargate is essentially the “I just want to run my containers” option. You provide AWS with your Docker image, specify your CPU and memory requirements, and it takes care of the underlying infrastructure. No EC2 instances to patch, no cluster capacity planning, and no late-night alerts about disk space issues.

A useful mental model: if EC2 is like owning a car (oil changes, tire rotations, that weird noise it keeps making), then Fargate is more like using a ride service. You specify your destination (run this container), and someone else handles the vehicle maintenance.

The Architecture

ECS with Fargate

Your Application

ECS Tasks

Fargate

AWS Manages Everything

Traditional ECS with EC2

Your Application

ECS Tasks

EC2 Instances

You Manage: OS, Patches, Scaling

The elegant part of this approach is the isolation model. Each Fargate task runs in its own environment with dedicated kernel, CPU resources, memory, and network interface. It’s similar to having a dedicated micro-VM for each container, but without the operational overhead that usually comes with VM management.

Your First Deployment

Here is a practical Fargate deployment on ECS. For a first deployment, ECS has fewer moving parts than EKS; unless you have a specific Kubernetes requirement, it is the simpler starting point.

The first step is creating a task definition, which is essentially telling AWS what resources your container needs:

{
  "family": "my-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "arn:aws:iam::111122223333:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "name": "my-app",
      "image": "nginx:latest",
      "portMappings": [
        {
          "containerPort": 80,
          "protocol": "tcp"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/my-app",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}

The execution role is easy to forget. Without it the task cannot pull the image or write to CloudWatch Logs, and it fails before your code runs.

A second detail that trips people up: the CPU and memory values are not arbitrary. Fargate supports specific combinations:

CPU (vCPU)Memory Values (GB)
0.250.5, 1, 2
0.51, 2, 3, 4
12, 3, 4, 5, 6, 7, 8
24-16 (1GB increments)
48-30 (1GB increments)
816-60 (4GB increments)
1632-120 (8GB increments)

If you pick an invalid combination, AWS will let you know and ask you to adjust. This often surfaces when a task definition is copied from an EC2 setup and the tasks won’t start.

Networking Considerations

Fargate only supports awsvpc network mode. Each task gets its own elastic network interface (ENI) with a private IP address. That is good for security isolation, but it means subnet sizing and ENI quotas become part of your capacity planning.

Here’s an example using Terraform (which is more manageable than console clicking for anything beyond initial experiments):

resource "aws_ecs_service" "my_app" {
  name  = "my-app-service"
  cluster  = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.my_app.arn
  desired_count  = 2
  launch_type  = "FARGATE"

  network_configuration {
    subnets  = aws_subnet.private[*].id
    security_groups  = [aws_security_group.ecs_tasks.id]
    assign_public_ip = false
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.my_app.arn
    container_name  = "my-app"
    container_port  = 80
  }
}

# Important: Fargate requires 'ip' target type, not 'instance'
resource "aws_lb_target_group" "my_app" {
  name  = "my-app-tg"
  port  = 80
  protocol  = "HTTP"
  vpc_id  = aws_vpc.main.id
  target_type = "ip"  # <-- This is crucial for Fargate
  
  health_check {
    enabled  = true
    healthy_threshold  = 2
    unhealthy_threshold = 2
    timeout  = 5
    interval  = 30
    path  = "/health"
    matcher  = "200"
  }
}

Fargate vs EC2: Decision Criteria

A quick way to frame the choice:

Where Fargate Fits

  • Unpredictable or spiky traffic
  • A team that would rather spend its time on application code than on hosts
  • Many small, isolated services
  • Compliance requirements that call for strong workload isolation
  • An existing container workflow

Where EC2 Fits

  • GPU workloads (Fargate has no GPU support)
  • Windows containers with specific host requirements
  • Predictable, high utilization where Reserved Instances or Spot cut the bill
  • Privileged containers or custom kernel modules
  • Anything that needs host-level access, such as node-level monitoring agents

Cost Considerations

Fargate costs more per unit of compute than EC2. For a service sized at 2 vCPU and 4 GB running around the clock in us-east-1, list prices land roughly here:

Option (2 vCPU, 4 GB)Monthly, running 24/7
EC2 t3.medium, On-Demand~$30
EC2 t3.medium, 1-year Reserved~$19
Fargate, On-Demand~$72
Fargate Spot~$22

Compute Savings Plans cover Fargate too, and the discount depends on the term and payment option you commit to.

Note: AWS pricing varies by region and changes over time. These are approximate list prices for illustration; check current pricing in your region.

Fargate Spot deserves special mention here. It offers up to 70% cost savings by running tasks on spare capacity, though tasks can be interrupted with 2-minute notice. For fault-tolerant workloads, it can make Fargate surprisingly cost-competitive.

What these numbers don’t capture is the operational overhead saved:

  • No OS patching and updates
  • No cluster capacity planning
  • No auto-scaling group management
  • No instance health monitoring
  • No capacity shortage emergencies

None of that shows up on an invoice, which is why the hourly comparison on its own overstates the gap.

Common Surprises

  1. Startup is not instant: image pull, ENI attachment, and the first health checks all happen before a task takes traffic. Plan for that gap in deployment and scale-out windows rather than assuming a task is live the moment it is scheduled.

  2. ENI limits: each Fargate task consumes an ENI and a subnet IP address. Hitting the network interface quota, or running out of addresses in a small subnet, stops tasks from launching. This tends to bite during a busy deployment day.

  3. No SSH Access: You can’t SSH into Fargate containers the traditional way. ECS Exec provides debugging access:

    aws ecs execute-command \
      --cluster my-cluster \
      --task abc123 \
      --container my-app \
      --interactive \
      --command "/bin/sh"

    This only works if the service was created with enableExecuteCommand and the task role can talk to SSM.

  4. Ephemeral storage: tasks get 20 GB of ephemeral storage by default and can be configured up to 200 GB. Past that, mount EFS and expect slower I/O than local disk.

  5. Platform Versions: Fargate pins each task to a platform version, and LATEST resolves to 1.4.0 on Linux. AWS moves these forward for you, which is usually fine and occasionally changes behavior. Test in staging first.

A Reference Architecture

A common production shape for a web service on Fargate:

AWS

Internet

Data Layer

Fargate Tasks

Users

Application Load Balancer

App Container 1

App Container 2

App Container 3

RDS

ElastiCache

S3 Bucket

What matters in this layout:

  1. Use ALB for load balancing - It integrates seamlessly with Fargate’s IP-based targets
  2. Put Fargate tasks in private subnets - Use NAT gateways for outbound internet
  3. Use Parameter Store or Secrets Manager - Don’t bake secrets into images
  4. Set up proper logging - CloudWatch Logs is fine to start, but consider Datadog or similar for production
  5. Monitor ENI allocation - It’s the resource you’ll run out of first

The Bottom Line

Start with Fargate for new containerized workloads and stay there until a specific constraint pushes you off: GPU access, privileged containers, custom kernel modules, or a steady load where Reserved Instances or EC2 Spot clearly win on price. If Fargate spend becomes the thing you argue about in planning, that is usually a good problem; it means the workload is predictable enough to justify the engineering time that cluster management costs.

A reasonable next step: size one non-critical service at 0.5 vCPU / 1 GB, run it behind an ALB with ip targets, and compare the bill against the EC2 host it would have replaced plus the maintenance that host needs.

References

AWS Fargate Deep Dive Series

Complete guide to AWS Fargate from basics to production. Learn serverless containers, cost optimization, debugging techniques, and Infrastructure-as-Code deployment patterns through real-world experience.

Progress 1/4 posts completed

Related posts