How to deploy and run containers on AWS with ECS and Fargate.
Amazon Elastic Container Service (ECS) is AWS's managed container orchestrator which runs containers from task definitions and connects them to AWS networking, IAM, load balancing, logging, and either serverless Fargate capacity or EC2 instances managed in your account.
This guide follows an image from Amazon ECR into a production ECS service. It covers tasks and services, Fargate and EC2 capacity, networking, deployments, autoscaling, observability, cost, and how ECS compares with EKS and higher-level application platforms.
We'll also look at how Encore can provision an application's ECS deployment and supported resources from declarations in code, reducing the task definitions, IAM, and networking configuration your team maintains directly.
By separating a workload description from its running instances, ECS can use the same task definition for a one-off migration or batch job and for a service that keeps an API running continuously.
ECS does not build the image - a typical workflow builds it in CI, pushes it to Amazon ECR, registers a new task-definition revision, and tells the service to deploy that revision.
For an orders API, the task definition identifies the image and gives ECS enough information to start it. This example uses Fargate, exposes port 8080, and sends the container output to CloudWatch Logs:
{
"family": "orders-api",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ordersTaskRole",
"containerDefinitions": [
{
"name": "api",
"image": "123456789012.dkr.ecr.eu-west-1.amazonaws.com/orders:abc123",
"essential": true,
"portMappings": [{ "containerPort": 8080, "protocol": "tcp" }],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/orders-api",
"awslogs-region": "eu-west-1",
"awslogs-stream-prefix": "api"
}
}
}
]
}
The task definition is versioned, so a deployment normally creates a new revision rather than editing the one already in production. The referenced image, log group, and IAM roles must exist before ECS starts the task.
ECS uses the execution role to pull the image and deliver logs, while the task role gives the application its own AWS permissions. An orders service can therefore write receipts to its S3 bucket without storing credentials in the image or an environment file.
Registering the JSON creates a task-definition revision; it does not start a container. RunTask is useful for work that should execute once, while an ECS service is the usual choice for an API because it continually reconciles the running tasks with a desired count.
Once a production service has subnets, security groups, and a capacity provider, ECS can register its healthy tasks behind an Application Load Balancer, drain old tasks as a revision comes online, and adjust the desired count through Service Auto Scaling.
Running a short ECS definition in production adds network access to databases and queues, permission for the load balancer to reach the task port, health checks that reflect startup time, and an outbound route or VPC endpoints for private tasks.
The cluster provides a logical home for the service, while capacity providers determine where its tasks run and, more importantly, who manages the underlying machines.
Fargate is the common starting point because each task receives the CPU and memory requested in its definition without requiring an EC2 fleet, while ECS continues to schedule the tasks and operate the service. Fargate supplies the compute; it is not a different orchestrator.
EC2-backed ECS becomes attractive when the workload needs instance types or host access that Fargate does not offer, or when a large, predictable fleet can use reserved and Spot capacity efficiently. The saving comes with node patching, AMI maintenance, scaling, and bin-packing work that Fargate removes.
During the rolling deployments ECS uses by default, minimum and maximum healthy percentages control how much capacity may disappear or be added, health checks decide when a new task can receive traffic, and the deployment circuit breaker can stop a failed release and return the service to its last completed version.
The circuit breaker works best when the container fails loudly through a health endpoint that reflects whether it can serve requests, a grace period matching its startup time, and termination handling that lets in-flight requests drain. Logs and deployment events should make it possible to distinguish an application crash from an image-pull, IAM, networking, or load-balancer failure.
For Fargate and self-managed EC2 capacity, there is no separate ECS management fee. ECS Managed Instances adds a per-instance management fee, and ECS Anywhere has its own charges. The bill also includes compute together with load balancers, public IPv4 addresses, NAT gateways, logs, ECR storage, data transfer, databases, and queues. A small service can spend more on fixed networking components than on its containers, so those resources belong in the estimate from the start.
ECS is a good fit when containers are already the unit you want to operate and the application belongs on AWS. If Kubernetes compatibility is required, use EKS; if the workload is a small event handler rather than a continuously running container, Lambda may be simpler.
Encore can set up an ECS Fargate deployment from the services and resources declared in your application code. It creates the task definitions, networking, and IAM configuration, then provisions and connects the databases, queues, and storage the application uses in your AWS account.
import { SQLDatabase } from "encore.dev/storage/sqldb";
const db = new SQLDatabase("todo", {
migrations: "./migrations",
});Managed PostgreSQL with migrations, pooling and IAM auth
Encore maps the resources declared by the application to managed services in the target cloud.
Shared networking and account infrastructure can remain managed by Terraform.
Run in your terminal to get started locally.
Amazon Elastic Container Service is AWS's managed container orchestrator. It schedules containers, replaces failed tasks, maintains the desired number of replicas, and coordinates deployments across Fargate, ECS Managed Instances, EC2, or external capacity.
No. ECS is the orchestrator, while Fargate is one of the compute options available to run ECS tasks. ECS can also place tasks on ECS Managed Instances, EC2 instances managed by your team, or registered external servers.
No. ECS has its own AWS-native control plane, APIs, task definitions, and service model. Amazon EKS is the corresponding AWS service for Kubernetes.
The ECS control plane has no separate charge, but you pay for the compute and supporting AWS resources used by the application, such as Fargate tasks or EC2 instances, load balancers, storage, logs, and data transfer.
Yes. Encore can derive supported application infrastructure from the resources declared in code and provision it in your AWS account, including ECS Fargate compute where appropriate.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.