Amazon ECS on Fargate: 6 Practical Tips for Running Containers Without Managed Servers
Six hard-won, practical tips for running real workloads on ECS Fargate — from right-sizing tasks to the deployment circuit breaker that saves production incidents.
Containers are great until you have to babysit the servers running them. Amazon ECS with Fargate launch type removes the EC2 layer entirely — you define tasks, Fargate provisions the compute. But 'serverless' doesn't mean 'carefree'. These six tips are what I'd tell anyone moving their first real workload to Fargate.
1. Right-size your task definitions from day one
Fargate bills on the CPU and memory you reserve, not what you use. The classic mistake is copying an EC2-era sizing mindset and reserving 2 vCPU / 4 GB for a service that idles at 0.1 vCPU. Start with the smallest valid combination for your workload (0.25 vCPU with 0.5 GB is fine for many small services), then use CloudWatch Container Insights to watch actual utilization for a week before locking in sizes. Right-sizing a handful of always-on tasks is one of the cheapest cost wins on AWS.
Fargate bills on the CPU and memory you reserve, not what you use. The classic mistake is copying an EC2-era sizing mindset and reserving 2 vCPU / 4 GB for a service that idles at 0.1 vCPU. Start with the smallest valid combination for your workload (0.25 vCPU with 0.5 GB is fine for many small services), then use CloudWatch Container Insights to watch actual utilization for a week before locking in sizes. Right-sizing a handful of always-on tasks is one of the cheapest cost wins on AWS.
2. Keep images small and scan them
Multi-stage Docker builds exist for a reason: ship only the runtime dependencies, not your build toolchain. Smaller images pull faster, which matters directly on Fargate because task startup time includes the image pull. Push images to ECR and turn on image scanning — a CVE in a base image you forgot about is an unpleasant surprise you don't want in production.
Multi-stage Docker builds exist for a reason: ship only the runtime dependencies, not your build toolchain. Smaller images pull faster, which matters directly on Fargate because task startup time includes the image pull. Push images to ECR and turn on image scanning — a CVE in a base image you forgot about is an unpleasant surprise you don't want in production.
3. Never put secrets in task-definition environment variables
Task definitions are configuration, and env values are visible to anyone who can describe the task. Use Secrets Manager or Systems Manager Parameter Store for credentials, and reference them via secrets in the container definition. Rotating a secret then becomes a single update instead of a redeploy-and-pray operation.
Task definitions are configuration, and env values are visible to anyone who can describe the task. Use Secrets Manager or Systems Manager Parameter Store for credentials, and reference them via secrets in the container definition. Rotating a secret then becomes a single update instead of a redeploy-and-pray operation.
4. Configure health checks and graceful shutdown
Add a HEALTHCHECK-style healthCheck to your container definitions so ECS stops routing to tasks that are alive but broken (the 'it responds but everything is wrong' failure mode). And respect SIGTERM: set a stopTimeout that gives your app time to drain in-flight requests. Without it, deployments kill connections mid-request and you get mysterious 5xx spikes every deploy.
Add a HEALTHCHECK-style healthCheck to your container definitions so ECS stops routing to tasks that are alive but broken (the 'it responds but everything is wrong' failure mode). And respect SIGTERM: set a stopTimeout that gives your app time to drain in-flight requests. Without it, deployments kill connections mid-request and you get mysterious 5xx spikes every deploy.
5. Front services with an ALB and enable the deployment circuit breaker
An Application Load Balancer with target groups per service gives you path-based routing and health-check-driven traffic shifting for free. Pair it with the ECS deployment circuit breaker (enable with rollback): if a new task set fails its health checks, ECS rolls back automatically instead of leaving your service half-deployed. That single setting has saved more production incidents than any runbook I've seen.
An Application Load Balancer with target groups per service gives you path-based routing and health-check-driven traffic shifting for free. Pair it with the ECS deployment circuit breaker (enable with rollback): if a new task set fails its health checks, ECS rolls back automatically instead of leaving your service half-deployed. That single setting has saved more production incidents than any runbook I've seen.
6. Logging and alarms from the first deploy, not the first incident
Use the awslogs log driver to send container logs to CloudWatch Logs from day one. Then add two alarms immediately: task restart rate (a restart loop is Fargate's version of CrashLoopBackOff and almost always means a bad image or config) and CPU/memory utilization. Fargate without observability is flying blind — except you're also paying per vCPU-second for the privilege.
Use the awslogs log driver to send container logs to CloudWatch Logs from day one. Then add two alarms immediately: task restart rate (a restart loop is Fargate's version of CrashLoopBackOff and almost always means a bad image or config) and CPU/memory utilization. Fargate without observability is flying blind — except you're also paying per vCPU-second for the privilege.
Key takeaways: right-size tasks and measure with Container Insights; ship small, scanned images via ECR; secrets go in Secrets Manager, never env vars; health checks plus graceful shutdown protect deployments; ALB plus the deployment circuit breaker gives you safe rollouts; log everything and alarm on restarts from day one.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article