AWS ECS
ECS task definitions, services, rolling deploys, and rollback.
Production backend services run on AWS ECS (Fargate). Docker images from Docker are pushed to ECR and deployed as ECS services behind an Application Load Balancer.
Architecture
Task definition
{
"family": "backend-api",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::ACCOUNT:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::ACCOUNT:role/backend-api-task-role",
"containerDefinitions": [
{
"name": "api",
"image": "ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/backend-api:latest",
"portMappings": [{ "containerPort": 4000, "protocol": "tcp" }],
"healthCheck": {
"command": ["CMD-SHELL", "wget -qO- http://localhost:4000/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
},
"environment": [
{ "name": "NODE_ENV", "value": "production" },
{ "name": "PORT", "value": "4000" }
],
"secrets": [
{ "name": "DATABASE_URL", "valueFrom": "arn:aws:secretsmanager:..." },
{ "name": "FCM_PRIVATE_KEY", "valueFrom": "arn:aws:secretsmanager:..." }
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/backend-api",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "api"
}
}
}
]
}The task role grants S3, SES, and Secrets Manager access. The execution role pulls ECR images and writes CloudWatch logs.
ECS service
{
"serviceName": "backend-api",
"cluster": "production",
"taskDefinition": "backend-api",
"desiredCount": 3,
"launchType": "FARGATE",
"loadBalancers": [
{
"targetGroupArn": "arn:aws:elasticloadbalancing:...",
"containerName": "api",
"containerPort": 4000
}
],
"deploymentConfiguration": {
"minimumHealthyPercent": 100,
"maximumPercent": 200,
"deploymentCircuitBreaker": {
"enable": true,
"rollback": true
}
}
}Deploy pipeline
# 1. Build and push (CI does this on merge to main)
docker build -t backend-api:$TAG .
docker tag backend-api:$TAG $ECR_REPO:$TAG
docker push $ECR_REPO:$TAG
# 2. Register new task definition with updated image
aws ecs register-task-definition --cli-input-json file://task-definition.json
# 3. Update service — rolling deploy
aws ecs update-service \
--cluster production \
--service backend-api \
--task-definition backend-api \
--force-new-deployment
# 4. Wait for stability
aws ecs wait services-stable --cluster production --services backend-apiRollback
# List recent task definition revisions
aws ecs list-task-definitions --family-prefix backend-api --sort DESC
# Roll back to previous revision
aws ecs update-service \
--cluster production \
--service backend-api \
--task-definition backend-api:42
aws ecs wait services-stable --cluster production --services backend-apiThe deployment circuit breaker auto-rolls back if new tasks fail health checks.
Socket.io on ECS
- ALB must support WebSocket upgrades (enabled by default on HTTP/HTTPS listeners)
- Enable sticky sessions (target group stickiness) if running multiple tasks — optional but recommended for Socket.io
- Health check path:
/health
Environments
| Environment | Cluster | Desired count | Notes |
|---|---|---|---|
| Alpha | alpha | 1 | Auto-deploy from develop |
| Beta | beta | 2 | Deploy from release branch |
| Production | production | 3+ | Manual approval in CI |