# ECS Early Success Criteria: onde termina o rollback do seu deploy

Em 4 de setembro de 2026 o Amazon ECS passou a deixar você declarar quando um rolling deployment é bem-sucedido, com um healthyPercent sobre o desired count. Isso não é um botão de deploy mais rápido — é a definição de onde o circuit breaker e o rollback por alarme param de proteger. Este briefing mostra a aritmética do parâmetro, os dois modos de limpeza da revisão fonte e o que o seu painel passa a esconder.

- URL: https://fernando.moretes.com/blog/ecs-early-success-criteria-onde-termina-o-rollback-do-seu-deploy-amazon-ecs-i

- Markdown: https://fernando.moretes.com/blog/ecs-early-success-criteria-onde-termina-o-rollback-do-seu-deploy-amazon-ecs-i/article.md?lang=pt

- Published: 2026-09-07T10:16:02.363Z

- Category: IA & Agentes

- Tags: ecs, deployments, ci-cd, reliability, containers, sre, aws

- Reading time: 8 min

- Source: [Amazon ECS introduces Early Success Criteria for service deployments](https://aws.amazon.com/about-aws/whats-new/2026/09/amazon-ecs-deployments-early-success/)

---

A pergunta que o Amazon ECS acabou de devolver para você não é quanto tempo o deploy demora — é a partir de qual ponto você aceita ficar sem rollback automático. Desde 4 de setembro de 2026, o `earlySuccessCriteria` permite fechar um rolling deployment quando uma fração das tasks está saudável, e a documentação diz em voz alta o que isso custa: depois que o deployment fecha, o circuit breaker e o rollback por alarme não revertem mais o serviço.

## Os três números que definem o recurso

- **90/100** — tasks saudáveis para fechar o deployment. Com `healthyPercent` 90 e desired count 100. As dez restantes sobem por service scaling comum, fora do ciclo de vida do deployment.
- **2 semanas / 2 we** — janela de limpeza no modo DEFERRED. O ECS tenta drenar as tasks da revisão fonte por até duas semanas depois do sucesso. Task protegida além disso nunca é limpa.
- **0** — novos status de deployment. O ciclo segue `IN_PROGRESS` → `SUCCESSFUL`. Nada no EventBridge ou no CloudTrail distingue um sucesso antecipado de um sucesso completo.

## O sinal: o deploy deixou de ser um contrato binário

Até agora, um rolling deployment do ECS só fechava quando quatro coisas eram verdade ao mesmo tempo: a revisão alvo chegava a 100% do desired count com todas as tasks rodando e saudáveis, nem o circuit breaker nem o alarme do CloudWatch disparavam rollback, o bake time do alarme passava, e as tasks da revisão fonte eram limpas. É um contrato de tudo ou nada, desenhado para frota homogênea que sobe em segundos.

O `earlySuccessCriteria`, disponível para a estratégia `ROLLING` em todas as regiões comerciais e no GovCloud (US), quebra esse contrato em dois. Você declara um `healthyPercent` — a fração do desired count que precisa estar rodando e saudável na revisão alvo — e o ECS fecha o deployment ali. Com desired count 100 e `healthyPercent` 90, o deployment vira `SUCCESSFUL` na task 90; as dez restantes sobem depois, por service scaling comum.

O caso que motiva isso é fácil de reconhecer: inferência acelerada por GPU. A cauda de uma frota em capacidade especializada não sobe na mesma velocidade que a cabeça — a variável é a disponibilidade de hardware, não o seu contêiner. O deployment fica aberto esperando duas tasks que dependem de instância, o pipeline atrás dele fica em fila, e o deploy seguinte não começa. O mesmo vale para o outro lado da troca: serviço com conexão longa, cuja revisão fonte demora para drenar e segura o deployment aberto por um motivo que não tem nada a ver com a saúde do código novo.

## Onde a proteção acaba: a linha do tempo do deployment

O mesmo deployment, dividido pela fronteira do sucesso. À esquerda, tudo é reversível; à direita, nada é.

### 🟧 AWS ECS — janela protegida (rollback ativo)

- earlySuccessCriteria enable=true, healthyPercent=90 (compute)
- 1ª task saudável / first healthy task pré-condição da avaliação (compute)
- Gate: 90 de 100 tasks arredondado p/ cima / rounded up (compute)
- Deployment circuit breaker BOUNDED_PERCENT 50 → 3..200 (security)
- CloudWatch alarm + bakeTimeInMinutes (security)

### 🔀 Cleanup da revisão fonte / source revision cleanup

- BLOCKING drena antes do SUCCESSFUL (messaging)
- DEFERRED SUCCESSFUL antes de drenar (messaging)

### 🟩 Fora do deployment — sem rollback / no rollback

- Service scaling 10 tasks restantes / remaining (compute)
- Tasks da revisão fonte scale-in protection ≤ 2880 min (compute)

### 📡 Sinais / observability

- DescribeServiceDeployments snapshot pós-sucesso (data)
- DescribeServices contagem viva / live counts (data)
- EventBridge IN_PROGRESS → SUCCESSFUL (messaging)

### Fluxos

- cicd -> cfg: aplica deployment-configuration
- cfg -> first: ECS espera 1 task saudável
- first -> gate: conta tasks saudáveis
- cb -> gate: pode reverter até aqui
- alarm -> gate: bake time antes de fechar
- gate -> blocking: cleanup = BLOCKING
- gate -> deferred: cleanup = DEFERRED
- blocking -> scaling: sucesso depois da drenagem
- deferred -> scaling: sucesso antes da drenagem
- deferred -> drain: drena assíncrono, até 2 semanas
- scaling -> ds: única fonte de contagem real
- gate -> dsd: congela os contadores
- gate -> eb: mesmo evento de sempre
- cicd -> eb: destrava o próximo deploy

## O que muda para quem desenha o serviço

- **Só existe em `ROLLING`:** as estratégias `BLUE_GREEN`, `LINEAR` e `CANARY` não têm `earlySuccessCriteria` — elas já resolvem o mesmo problema por deslocamento de tráfego, e com outro custo.
- **O intervalo é fechado pelo `minimumHealthyPercent`:** o `healthyPercent` é inteiro entre 0 e 100 e precisa ficar entre o `minimumHealthyPercent` do serviço e 100. Com o padrão de 100% para serviços replica, não sobra intervalo nenhum.
- **Arredonda para cima:** desired count 3 com 50% fecha em 2 tasks, não em 1. Desired count 10 com 80% fecha em 8. Em serviço pequeno o ganho é zero.
- **Não existe atalho para zero:** o ECS lança pelo menos uma task na revisão alvo e espera ela ficar saudável antes de avaliar o percentual. Código quebrado não fecha cedo — falha.
- **Fechou, acabou:** circuit breaker e rollback por alarme param de agir depois do sucesso, inclusive enquanto as tasks restantes sobem. Um deployment concluído não pode ser interrompido.

## A fronteira que você está movendo é a do rollback

Ler isso como deploy mais rápido é ler errado. O `healthyPercent` não é um acelerador — é a declaração de onde termina a proteção automática. A documentação é explícita: depois que o ECS completa o deployment, o circuit breaker e o rollback por alarme deixam de reverter o serviço, inclusive durante a subida das tasks restantes por service scaling.

Traduzindo para plantão: com desired count 100 e `healthyPercent` 90, as dez últimas tasks sobem sem rede. Se a nonagésima quinta falhar por um motivo que só aparece com carga real — connection pool estourando, um secret que só resolve numa AZ, um limite de licença por instância —, o ECS a substitui pela mesma revisão alvo, repetidamente, sem voltar para a revisão anterior. O modo de falha não é o deployment falhar; é o deployment passar e o serviço degradar devagar, com o pipeline já verde e a equipe já em outra tarefa.

O circuit breaker ainda protege a janela que sobrou, e vale saber com que sensibilidade. O tipo padrão `BOUNDED_PERCENT` multiplica o valor (padrão 50) pelo desired count e limita o resultado entre 3 e 200: com 100 tasks desejadas são 50 falhas toleradas antes do rollback; com 400, o teto de 200 vale. Pior: com `resetOnHealthyTask` em `true` — o padrão —, o contador zera a cada task saudável, então falhas intercaladas nunca somam. Encurtar a janela protegida com `healthyPercent` e deixar o circuit breaker no padrão permissivo é aplicar dois relaxamentos ao mesmo tempo e chamar isso de agilidade.

## BLOCKING ou DEFERRED: a mesma flag, dois riscos diferentes
| Critério | BLOCKING | DEFERRED |
| --- | --- | --- |
| Quando vira SUCCESSFUL | Depois do `healthyPercent`, do bake time e da limpeza das tasks da revisão fonte. | Depois do `healthyPercent` e do bake time. A limpeza acontece fora do deployment. |
| Tasks da revisão fonte | Já foram embora quando o pipeline recebe o sinal verde. | Podem seguir rodando; o ECS tenta drená-las por até duas semanas. |
| Custo em capacidade | Previsível: as duas revisões coexistem apenas dentro da janela do deployment. | Duas revisões cobrando ao mesmo tempo por tempo indeterminado, dentro do `maximumPercent`. |
| Risco que você aceita | Deployment mais longo se a drenagem tiver cauda longa; timeout de ferramenta de CI/CD. | Tráfego servido por código antigo depois do deploy declarado bem-sucedido. |
| Use quando | É o seu padrão. Escolha esta salvo motivo escrito para não escolher. | Conexão longa, sessão de jogo, job assíncrono ou task scale-in protection com expiração curta. |

## Escolher o número com aritmética, não com fé

Três restrições fecham o intervalo antes de qualquer opinião. Primeira: o `healthyPercent` precisa ser maior ou igual ao `minimumHealthyPercent` do serviço. Se você manteve o padrão de 100% de serviço replica, não existe intervalo nenhum — baixar o `minimumHealthyPercent` é pré-requisito, e ele governa quantas tasks o scheduler pode parar durante a troca, o que é uma decisão de capacidade, não de velocidade.

Segunda: o valor é arredondado para cima sobre o desired count. Com 3 tasks e 50%, o deployment fecha em 2. Com 10 e 80%, em 8. Em serviço pequeno cada ponto percentual vale uma task inteira, e o ganho de tempo tende a zero: o `earlySuccessCriteria` só paga em frota grande ou em capacidade lenta.

Terceira: o ECS lança ao menos uma task na revisão alvo e espera ela ficar saudável antes de avaliar o percentual. E uma task só conta como saudável depois de passar os health checks configurados — com load balancer, isso significa o health check do target group, e com contêiner essencial com health check definido, os dois.

Daí em diante é decisão de risco, e ela é condicional. Use 90% ou mais quando o serviço é stateless atrás de ALB e o health check exercita dependência real, não um `/healthz` que devolve 200 sem tocar em nada. Fique em 100% — ou não ligue o recurso — quando a cauda de tasks carrega estado, shard ou licença por instância. E se a motivação é o pipeline demorar, meça antes: em rolling deployment, o tempo costuma morar no `healthCheckGracePeriodSeconds`, no `startPeriod` do health check do contêiner e no deregistration delay do target group — nenhum deles muda com a regra de sucesso.

> **DEFERRED tem prazo de validade:** No modo `DEFERRED`, o ECS tenta limpar as tasks da revisão fonte por até duas semanas depois do sucesso — e não consegue parar task com scale-in protection ativa. A proteção tem teto de 2880 minutos (48 horas) por chamada, mas é renovável: um worker que renova a própria proteção em loop mantém a revisão antiga viva além da janela e o ECS desiste. Some a isso o timeout de 3 horas do `update-stack` do CloudFormation e você tem duas revisões cobrando ao mesmo tempo, servindo tráfego, sem ninguém observando — porque o deployment que as criou já está marcado como bem-sucedido. Instrumente a idade das tasks da revisão fonte via `DescribeServices`; não existe alarme pronto para isso.

## O que o painel passa a dizer — e o que deixa de dizer

O recurso não inventa status novo. O ciclo continua `IN_PROGRESS` → `SUCCESSFUL`, os eventos de service deployment state change no EventBridge e os registros do CloudTrail são os mesmos, e um deployment que fechou cedo aparece normalmente quando você filtra `ListServiceDeployments` por `SUCCESSFUL`. Isso é excelente para compatibilidade e péssimo para auditoria: nenhum consumidor do seu event bus consegue distinguir subiu inteiro de subiu 90% e o resto virou problema do autoscaling. Se o seu processo de mudança precisa dessa distinção — e sob BACEN, PCI-DSS ou SOX ele precisa —, a fonte é o `DescribeServiceDeployments`, que devolve a configuração de early success criteria junto com o deployment.

Há uma armadilha silenciosa nos contadores. Enquanto o deployment está em andamento, o `DescribeServiceDeployments` devolve contagem viva; depois que ele fecha, devolve um snapshot do momento do fechamento, nos dois modos de cleanup. Um dashboard que lê task count dali vai mostrar 90 para sempre, mesmo com 100 tasks rodando e mesmo com a revisão fonte ainda drenando. A contagem viva está no `DescribeServices`, e só nele.

Então o alarme que importa muda de lugar. Antes, uma regra de EventBridge com `eventName` igual a `SERVICE_DEPLOYMENT_FAILED` cobria a maior parte do risco de release; agora ela cobre apenas a janela até o `healthyPercent`. O que passa a merecer alarme é a diferença entre `desiredCount` e `runningCount` da revisão alvo alguns minutos depois do sucesso, o número de substituições de task por revisão, e a idade das tasks da revisão fonte no modo `DEFERRED`. Nenhum desses três vem de graça.

## Como isso vai ser usado errado

- **`healthyPercent` como acelerador de pipeline:** baixar para 50% porque o build demora é comprar minutos de pipeline com metade da frota subindo sem rollback automático. O tempo estava nos timers de health check e drenagem, não na regra de sucesso.
- **Mesmo valor para todo serviço via módulo Terraform compartilhado:** o número certo depende de desired count, de custo de capacidade e de o serviço carregar estado. Um `healthyPercent` global é a definição de configuração que ninguém revisa.
- **`DEFERRED` combinado com scale-in protection renovada em loop:** as tasks antigas viram permanentes, o ECS desiste depois de duas semanas e você descobre pela fatura, não pelo painel.
- **Manter o dashboard de release lendo `DescribeServiceDeployments`:** depois do sucesso os contadores viram snapshot. O painel fica verde e imóvel enquanto a cauda da frota faz o que quiser.

> **O que realmente mudou:** O que mudou não é a duração do deployment — é quem responde pela cauda. Com `earlySuccessCriteria`, a subida das últimas tasks migra do plano de deployment, que tem rollback, circuit breaker e evento de falha, para o plano de service scaling, que não tem nenhum dos três. É a mesma escolha que você já faz ao definir um SLO: aceitar erro conhecido em troca de velocidade. A diferença é que aqui a escolha vira um inteiro num arquivo de infraestrutura como código, e inteiro em arquivo de IaC não passa por revisão de risco — passa por revisão de sintaxe.

> **Nota de curadoria:** Eu ligaria isso hoje em exatamente um tipo de serviço: inferência em capacidade especializada, onde a cauda de tasks depende de disponibilidade de hardware e não do meu código — e ainda assim com `healthyPercent` em 90, `sourceServiceRevisionCleanup` em `BLOCKING` e o circuit breaker trocado para `thresholdConfiguration` do tipo `COUNT`, com valor baixo, justamente porque a janela protegida ficou menor. Em serviço de pagamento eu não ligaria: o ganho é de minutos de pipeline e a perda é o rollback automático sob carga real, que é exatamente o controle que eu não consigo reconstruir às 2h da manhã. A lição que me custou caro em plataforma financeira: todo mecanismo que destrava o pipeline cobra a conta na primeira falha que só aparece com tráfego de produção, e a conta chega no plantão, não na retrospectiva. Antes de mexer no critério de sucesso, eu meço onde o deployment gasta tempo de verdade — quando a resposta é grace period e deregistration delay, o `healthyPercent` não teria mudado nada e o risco teria sido assumido de graça.

## Fontes

- [Amazon ECS introduces Early Success Criteria for service deployments (AWS What's New, 04/09/2026)](https://aws.amazon.com/about-aws/whats-new/2026/09/amazon-ecs-deployments-early-success/)
- [Complete Amazon ECS rolling deployments early with early success criteria](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/early-success-criteria.html)
- [DeploymentEarlySuccessCriteria — Amazon ECS API Reference](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DeploymentEarlySuccessCriteria.html)
- [DeploymentConfiguration — Amazon ECS API Reference](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_DeploymentConfiguration.html)
- [How the Amazon ECS deployment circuit breaker detects failures](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-circuit-breaker.html)
- [Protect your Amazon ECS tasks from being terminated by scale-in events](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-scale-in-protection.html)
- [Deploy Amazon ECS services by replacing tasks (rolling update)](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-ecs.html)
- [What Actually Happens During an ECS Rolling Deployment — Muhammad Raza](https://muhammadraza.me/2026/what-actually-happens-during-an-ecs-rolling-deployment/)

## Veredito

Ligue o `earlySuccessCriteria` quando a cauda do seu deployment depende de capacidade que você não controla — GPU, instância especializada, drenagem de conexão longa — e quando o serviço é stateless atrás de um health check que exercita dependência de verdade. Nesse caso: `healthyPercent` entre 90 e 95, `BLOCKING` como padrão, `DEFERRED` só onde existe conexão longa ou scale-in protection com expiração curta e monitorada, circuit breaker em `COUNT` para compensar a janela protegida menor, e um alarme novo sobre a diferença entre `desiredCount` e `runningCount` alguns minutos depois do sucesso. Não ligue como remédio para pipeline lento: o tempo de um rolling deployment mora nos timers de health check e drenagem, e trocar a regra de sucesso apenas move o risco para depois do rollback. O padrão `enable: false` continua correto para a maioria dos serviços — este é um recurso de exceção bem desenhado, com a fronteira documentada em voz alta, e não uma nova linha de baseline.

**Rating:** Ligar por exceção, não por padrão / Enab
