O que é canary deployment? Um guia prático para devs
Resumo
Um canary deployment envia a nova versão para uma pequena parcela do tráfego real, muitas vezes de 1% a 5%, antes de todos a receberem. Você compara a taxa de erro e a latência com a versão estável, amplia a fatia se tudo estiver bem e zera o peso do canário se não estiver. Ele limita o dano de uma release ruim, mas exige métricas por versão e tráfego suficiente para que o resultado signifique alguma coisa.
O que é canary deployment? É um lançamento em que a nova versão da sua aplicação recebe primeiro uma pequena fatia do tráfego real, digamos de 1% a 5%, enquanto todos os outros continuam na versão antiga. Você acompanha a taxa de erro e a latência nessa fatia. Se ela parecer saudável, você amplia. Se parecer ruim, devolve o tráfego para a versão estável e quase ninguém percebe. Essa é a ideia, e o resto do artigo mostra como fazê-la funcionar na prática.

Por que se chama canary?
Mineiros levavam canários para dentro das minas porque a ave reagia ao gás tóxico antes das pessoas. Um canário que parava de cantar era o sinal para sair. No deploy a lógica é parecida: um pequeno grupo de usuários encontra o código novo primeiro e funciona como alerta precoce. O glossário da CNCF descreve o método como dois ambientes, um servindo o tráfego real e outro com o código atualizado, com o tráfego sendo transferido aos poucos, começando por uma fatia pequena como 1%.
Na prática, o detalhe que importa é que os usuários do canário são usuários reais. Staging não reproduz isso. Produção tem navegadores estranhos, caches desatualizados e aquele cliente com um arquivo de importação de 40 MB. O canário é a forma de encontrar esses casos antes que todos encontrem o seu bug.
Como um canary deployment funciona de fato?
São quatro peças, nada exótico.
Duas versões rodando lado a lado. A antiga (estável) e a nova (canário). As duas precisam conseguir atender requisições ao mesmo tempo.
Um divisor de tráfego. Um load balancer, um ingress controller, um service mesh ou uma regra de CDN que envia uma porcentagem configurável para o canário.
Métricas em que você confia. Taxa de erro, latência e pelo menos um sinal de negócio, como sucesso no checkout ou novos cadastros.
Uma regra para avançar ou abortar. Escrita antes do deploy, e não inventada às 23h olhando gráficos.
Uma rampa típica fica assim: 1%, 5%, 25%, 50%, 100%, com uma pausa em cada degrau. A documentação do Google Cloud Deploy descreve a mesma forma: você define uma sequência de percentuais e a ferramenta distribui o tráfego, com um exemplo que usa fases de 25%, 50% e 75% antes da versão estável final. A documentação de canary do Cloud Deploy também mostra que cada fase pode rodar um job de verificação e uma etapa de análise para decidir se avança.
Não é uma configuração perfeita, mas é viável. Você não precisa de Kubernetes para isso. Uma rota ponderada no nginx, uma regra de Cloudflare Worker que grava um cookie ou duas máquinas no Fly.io atrás de um mesmo proxy, tudo isso conta.
Como fica o divisor de tráfego em uma configuração?
Aqui vai o menor exemplo útil: um upstream do nginx com pesos. Nove em cada dez requisições vão para a estável, uma vai para o canário.
upstream app {
server 10.0.0.10:3000 weight=9; # estável
server 10.0.0.11:3000 weight=1; # canário
}Esse exemplo tem uma falha que você precisa conhecer: a divisão é por requisição, então um mesmo usuário pode alternar entre versões em cliques seguidos. Se a nova versão muda o formato de uma resposta de API ou de uma coluna do banco, esse usuário vai ter uma experiência ruim. Roteamento fixo por cookie ou por ID de usuário resolve isso, e é a primeira coisa que vale adicionar depois que a divisão básica funciona.

O que observar enquanto o canário roda?
Compare o canário com a versão estável no mesmo momento, e não com a semana passada, porque a semana passada tinha outro tráfego. A pergunta é sempre: o canário está pior do que a versão que atende os outros 95% agora?
Taxa de erro. Respostas HTTP 5xx e exceções não tratadas, separadas por versão.
Latência. p95 e p99, e não a média. A média esconde a cauda lenta, onde moram as regressões.
Saturação. CPU, memória e conexões com o banco. Um vazamento aparece como uma inclinação, então dê tempo para ele se mostrar.
Uma métrica de negócio. Se o sucesso do checkout cai no canário enquanto os erros continuam estáveis, você lançou um bug silencioso.
O erro mais comum em times pequenos é avançar por cronômetro: cinco minutos em 1%, depois 25%, independentemente do que os gráficos mostram. Com pouco tráfego, cinco minutos em 1% podem ser seis requisições, e isso não diz nada. Espere um número mínimo de requisições, e não um número mínimo de minutos.
Ferramentas que automatizam essa parte valem uma olhada quando você já tem tráfego real.
Canary ou blue-green: qual escolher?
Blue-green mantém dois ambientes completos e troca todo o tráfego de uma vez. O rollback é desfazer a troca, rápido e limpo. O custo é que, por um instante, 100% dos usuários estão na versão nova, e você paga pela infraestrutura dobrada durante a troca.
O canary expõe só uma fatia, então o raio de impacto é menor. O preço é a complexidade: você precisa de divisão de tráfego, métricas por versão e uma regra de decisão. O rollback significa zerar o peso do canário, o que é rápido, mas não é literalmente instantâneo se as conexões precisarem ser drenadas.
Três motivos para escolher canary e um para não escolher. Use canary quando um bug em produção sai caro, quando você tem tráfego suficiente para que uma fatia pequena signifique algo e quando consegue comparar métricas por versão. Evite quando você tem algumas dezenas de usuários por dia: a fatia do canário vai estar estatisticamente vazia e você vai estar chutando. Nessa escala, blue-green, ou até um deploy simples com um script de rollback rápido, é a resposta honesta.
Os rolling updates ficam no meio do caminho. Eles substituem instâncias uma a uma, o que é suave, mas não são um experimento controlado: você não escolhe quem vê a versão nova nem compara grupos.
Onde entram as feature flags?
Um canary deployment divide o tráfego entre versões do código. Uma feature flag divide o comportamento dentro de uma mesma versão. As pessoas confundem os dois, e a confusão sai cara.
Faça o deploy do código novo para todo mundo, escondido atrás de uma flag desligada. Depois ligue a flag para 1% dos usuários, depois 10%, depois todos. Isso costuma ser chamado de canary release no nível da funcionalidade. A vantagem é que o rollback vira desligar a flag, sem novo deploy. A desvantagem é que o caminho de código morto fica em produção para todo mundo, e flags esquecidas viram dívida técnica.
Para um dev solo, flags costumam ser o primeiro passo mais barato. Um booleano em uma tabela de configuração e um hash do ID do usuário já entregam uns 80% do valor. Se você crescer além disso, um serviço gerenciado cuida de segmentação, logs de auditoria e liberações graduais por porcentagem.

O que dá errado com canaries em projetos reais?
Testado, não é ótimo. Mesmo assim, veja por que continuamos fazendo. Estas são as falhas que de fato mordem.
Migrações de banco. As duas versões acessam o mesmo banco ao mesmo tempo. Se o canário remove ou renomeia uma coluna, a estável quebra. A correção é o padrão expand and contract: adicione a coluna nova primeiro, envie código que lida com as duas formas e só remova a antiga em uma release posterior. Pular isso faz o seu canário derrubar a versão estável.
Sessões com estado. Se as sessões vivem na memória de uma instância, um usuário que alterna entre versões é deslogado. Mova o estado da sessão para um armazenamento compartilhado antes de tentar canaries.
Cache envenenado. Uma versão nova que grava outro formato de cache pode corromper o que a versão antiga lê. Versione as chaves do cache.
Jobs em segundo plano. O canário também consome mensagens de fila. Um worker com bug pode consumir jobs na velocidade máxima, porque a porcentagem de tráfego não limita o consumo da fila. Dê ao canário a sua própria fila ou um peso de consumidor.
Alertas que ninguém configurou. O canário pode falhar de forma barulhenta em um painel que ninguém abre. Um aborto automático por limiar vence um humano olhando a tela, principalmente às 2h da manhã em São Paulo, quando a única pessoa acordada é quem fez o deploy.
Como começar com um canary em um projeto pessoal?
Comece menor do que você acha que deveria. Você é um dev, não um time de plataforma.
Marque cada métrica com uma versão. Coloque o SHA do git em um header e nos logs. Sem isso, você não consegue comparar canário e estável.
Escolha uma regra de aborto. Por exemplo: taxa de erro do canário acima de 2x a da estável por cinco minutos significa rollback. Uma regra só, escrita.
Adicione uma rota ponderada. Pesos no nginx, uma regra na Cloudflare ou o recurso de divisão de tráfego da sua hospedagem. A maioria das plataformas gerenciadas já oferece roteamento por porcentagem sem ferramentas extras.
Envie algo simples primeiro. Uma mudança de texto, e não a reescrita da página de preços. Pratique a rampa e o rollback quando nada está em jogo.
Cronometre o rollback. Execute de verdade pelo menos uma vez. Se levar dez minutos de tentativas e erros, isso é o que precisa ser consertado, e não a rampa.
Se o seu projeto ainda está na fase de descobrir quem paga por ele, isso provavelmente é cedo demais. Publique de forma simples, mantenha um script de rollback e volte aos canaries quando uma queda puder custar clientes de verdade. Se você já está nessa fase, a rota ponderada somada a uma regra de aborto é um fim de semana de trabalho, e se paga na primeira vez que uma release ruim morre em 1% em vez de 100%.
Vale usar canary para tudo?
Não. Mudanças de configuração, ajustes de texto e a correção de um erro de digitação no rodapé não precisam de rampa. Use canary nas mudanças em que errar custa dinheiro ou confiança: pagamentos, autenticação, modelos de dados e qualquer coisa no caminho quente. Um pipeline que faz rampa em todo commit, levando uma hora, vai ser ignorado na primeira vez que alguém tiver pressa, e um processo ignorado é pior do que processo nenhum.
Então, qual é a mudança mais arriscada da sua próxima release, e o que seria preciso para mandá-la para 1% dos usuários primeiro?