ECS without tears: a deploy pipeline that is genuinely boring
Cloud & DevOps · May 2026 · 7 min read
Docker build, ECR push, rolling update, health check, done. The interesting part is everything I deliberately left out.
The pipeline I use on every ECS project is four stages and about ninety lines of YAML. It has not changed materially in three years, and that is the whole point. A deploy pipeline is infrastructure you should stop thinking about.
The four stages
- Build: multi-stage Dockerfile, so the runtime image carries no compilers or dev dependencies.
- Push: immutable tag from the commit SHA. Never latest, in any environment.
- Migrate: a one-off ECS task that must exit zero before the service update starts.
- Update: rolling deployment behind a health check, with circuit breaker rollback enabled.
Tagging by commit SHA is the single highest-leverage line in the file. It makes a rollback a redeploy of an artifact that has already been built and already been running, rather than a rebuild from a git tag under pressure at 6pm.
IMAGE=$REGISTRY/app:$GITHUB_SHA
docker build --target runtime -t $IMAGE .
docker push $IMAGE
aws ecs run-task --overrides migrate.json # must exit 0
aws ecs update-service --force-new-deployment
# rollback == update-service with the previous SHA
What is deliberately missing
No bespoke deploy script living on one engineer's laptop. No manual migration step in a runbook. No staging environment that was hand-built in the console two years ago and now differs from production in ways nobody can enumerate. Every environment comes from the same template with different parameters.
If a deploy needs a human in a terminal, it is not finished — it is a rehearsal.
Health checks deserve more care than they usually get. Point them at an endpoint that touches the database and the queue connection, not one that returns a static string. A container that is listening but cannot reach its dependencies should fail the check and be replaced, not quietly serve errors while the dashboard stays green.
Takeaways
- Tag images by commit SHA so rollback is a redeploy, never a rebuild.
- Gate the service update on a migration task that must exit zero.
- Health-check the dependencies, not just the process.
All notes · Shehzad Aslam