Executando verificação de segurança...
28

Como minha equipe fez 100 deploys pra produção numa sexta feira

Oi, eu sou o Chris 👋

Já postei algumas vezes aqui sobre os SaaS que venho construindo, e prometo que dessa vez não tem jabá (só um pouco de bastidor técnico que achei que valia compartilhar).

Geralmente deixo esse tipo de conteúdo pro dev.to, mas esse assunto rendeu mais do que eu esperava, então resolvi trazer aqui também.


💥 O Tweet

Na última sexta, eu publiquei esse tweet:

Sim, é verdade, nós fizemos 100 deploys na sexta. E sim, é muita coisa.

Isso foi na AbacatePay 🥑, onde construímos tudo em público e fazemos tudo com entrega contínua. Como vejo poucos relatos brasileiros sobre CD em larga escala, achei que seria legal explicar como fazemos isso acontecer.

👨‍👩‍👧‍👦 Como o time funciona

Nosso time tem 9 devs (11 contando os sócios).
Todos sabem no que cada um está trabalhando.
A comunicação rola tanto de forma síncrona quanto assíncrona, e temos um processo sólido de RFCs (Request for Comments), onde debatemos e alinhamos as ideias antes de codar.

Cada dev conhece pelo menos uma feature de ponta a ponta, mas todos contribuem em tudo que se sentirem confortáveis — mesmo que não dominem 100%.

🔄 O processo

Nosso fluxo de trabalho gira em torno de integração e entrega contínua, e um bom exemplo disso é nosso SDK em Node.js:

  • Cada PR é aberto por quem fez a tarefa.
  • O review é feito por quem cuida daquela feature.
  • Quando aprovado, o código vai pra main — sem firula de git flow. Usamos trunk-based development.

✂️ PRs pequenos, mudanças independentes

Cada PR é pequena e específica. A ideia é que cada commit faça uma única coisa.

Por exemplo, digamos que estou trabalhando no comprovante de transação. A estrutura da tarefa ficaria algo assim:

# Comprovante de transação
[documentação, links, RFC]

- incluir campo receiptUrl no model de Transaction
- salvar dados do pagador na Transaction
- criar tela de comprovante
  - busca receipt pela transaction recebida na URL
  - exibe recebedor e pagador
  - opção de download em PDF

Cada subtask é independente. E aí você pode se perguntar:

"Mas como testar o front sem ter o backend pronto?"
"Como saber os campos que vão no comprovante?"

A resposta: RFC.
Com tudo documentado, os devs podem trabalhar em paralelo sem precisar se alinhar o tempo todo.

🚀 Um exemplo prático

Se eu começasse hoje pela task incluir campo receiptUrl, eu faria dois commits simples:

  1. Adiciona o campo receiptUrl no schema do banco.
  2. Retorna o campo na API.

O receiptUrl é só o nosso domínio + o ID da transação. Fácil.

Depois disso, abro o PR. Não preciso esperar os dados do pagador estarem prontos — já sei, via RFC, o que vai estar ali depois.

A próxima task, salvar dados do pagador, gera outro PR, com um commit por banco parceiro e uma migration pra popular dados antigos.

E assim vai.

⚙️ CI/CD na prática

Nosso processo de CI/CD verifica:

  • Nome e descrição da PR
  • Evidências e screenshots (quando faz sentido)
  • Linter e testes passando
  • Build funcionando
  • Se há riscos ou regressões

PR aprovada → merge na main → deploy automático.

Se for reprovada, sempre tem um motivo claro e uma discussão saudável sobre simplicidade ou clareza.

🚧 Subir feature incompleta? Tudo bem!

Nem toda feature precisa estar 100% pronta pra ir pra produção.
A gente usa feature flags pra isso.

Se uma parte da feature ainda não está implementada, mas o código já está testado e não quebra nada, ela sobe assim mesmo — escondida atrás de uma flag.

Exemplo: no comprovante de transação, se a tela está pronta mas o download em PDF ainda não, subimos a tela com a flag RECEIPT_ENABLED: true, e o botão de download fica atrás de RECEIPT_PDF_DOWNLOAD: false.

Isso permite que:

  • O time continue trabalhando em paralelo sem se bloquear.
  • A gente já teste partes da feature em produção (com dados reais).
  • Evite branches gigantes e conflitos desnecessários.

E claro, ao finalizar tudo, basta ativar a flag — sem precisar fazer um novo deploy.

🎯 Por que isso importa?

Nosso maior valor está em ouvir nossos clientes.
Toda startup pequena é, no fundo, uma consultoria pros seus clientes principais.

A gente faz várias entregas por dia pros nossos maiores clientes. Eles não querem algo pronto como nos concorrentes — eles querem ser ouvidos. Querem solução rápida pros próprios problemas.

E pra isso, a gente precisa iterar rápido.


Se você achou esse post útil, curte aí ou comenta — posso detalhar mais sobre nossos processos, RFCs ou até sobre como usamos feature flags. Valeu por ler até aqui! 🥑

Carregando publicação patrocinada...
5

Cara, 100 deploys num mês da 25 por semana, já é muito, deveria ser exagerando 1 deploy nightly por dia, das duas uma uma, ou você tem um problema de qualidade de PR (cada commit vira um PR) ou você está confundindo "deploy" com a construção de teste de um PR e mesmo assim, qualquer um desses detalhes tem algum problema de logística

2

Não tem confusão nenhuma! Realmente cada PR ao ser mergeada é realizado um novo deploy.

Parece loucura, mas grandes startups fazem isso a todo momento. Isso tudo facilita em iterar melhor e com qualidade.

O segredo de tudo é ter um time enxuto e com boa comunicação, com todos alinhados e tudo bem descrito, é bem fácil revisar um PR pois ele já vem com todo o contexto necessário pra fazer a review

6

Sabia que tinha um caroço, são 12 PRs por hora para gerar esse volume de deploys, é inviável mesmo em projetos gigantes, o que acontece que vocês não fazem commit squash, e isso não é um elogio, o que vocês estão fazendo é literalmente o
oposto de algo limpo e ironicamente dificulta fazer o que disse que facilita na verdade, dificuldade, micro PRs são tão problemáticos quanto PRs gigantescos

1

Esse volume não é regra, foi o resultado de um fim de sprint com correção de bugs, melhorias para clientes específicos e também preparação para iniciar a sprint atual sem interferências de tarefas anteriores.

O maior problema em verem valor nesse tipo de operação, é que a maioria das equipes não tem o nível de comunicação e de documentação que nós temos. Também não é várzea, existe ordem no "caos"

2

Eu honestamente não entendo essa rapaziada que fica se perguntando se isso funciona em um time grande. O processo é simples e direto e funciona pra realidade de vocês. É isso que importa. Vocês testaram e validaram, é isso que importa.

11 pessoas conseguem se alinhar muito mais rápido, concordar mais rápido e entregar mais rápido. A qualidade vai virar consequência desse processo. Se todo mundo se entende, não tem erro.

Se ficou dúvida, replaneja. Se ninguém concorda, conversa. Se não ficou legal, paciência, refaz.

100% do que eu faço hoje com meu time é isso daí. Sucesso Chris.

2

Entendo que cada equipe possui seus próprios fluxos de trabalho, mas discordo da abordagem de subir funcionalidades em pequenos trechos diretamente em produção. Isso, na prática, transforma o ambiente de produção em um ambiente de testes, o que considero arriscado. Acredito que o mais saudável é subir algo sólido, validado com testes automatizados, revisado por QA e passando por um Code Review que permita uma análise mais profunda e estruturada. Do jeito que está sendo feito atualmente, há o risco de códigos ficarem esquecidos ou funcionalidades acabarem não sendo utilizadas no futuro.

2

Tudo vai parar em produção com testes e debaixo de feature flags. Isso já é suficiente para termos um time 100% autônomo. O principal é ter um time bem comunicativo onde todos sabem o que está sendo feito e por quem.

Sei que parece uma grande várzea, onde todos sobem alterações de forma desordenada e o mais rápido possível, mas na verdade não é assim. Temos RFCs, daylies e comunicação escrita e pública.

Sem isso, seria um monte de gente fazendo coisas de forma descoordenada, o que não reflete o nosso caso

2

Fiquei com uma dúvida onde você fala que o processo de CI/CD verifica "Se há riscos ou regressões".

Como isso é feito? É automatizado? Alguma ferramenta específica que faz essa validação?

1

Temos automações para verificar inclusão de pacotes malicosos e se existe também a necessidade de fazer upgrade de pacotes. Ferramentas como Snyk e Dependabot auxiliam nisso

2

Parabéns pelo conteúdo Chris! Essa ideia da feature flag é bem bacana para diminuir o problema das grandes features branchs, vou começar a implementar hoje isso por aqui!

2

Fazia muito tempo que eu não escutava alguém falar em feature flag, usei algumas vezes em algumas empresas em que trabalhei. Processo interessante esse, só não sei se funcionaria bem em um ambiente maior de desenvolvimento.

Sobre o pipeline de desenvolvimento, vocês possuem ambiente de QA ou homologação? Não sei se poderia explicar como funciona o processo de validação antes de entrar na master e Prod.

3

Não temos ambiente de QA/homologação.

Então como funciona? Temos testes e2e que rodam durante o CI. E também temos contas de testes que são isoladas do resto da aplicação (por ser um gateway de pagamentos, tudo é multi tenant). O time realiza os testes naquelas contas de teste antes de liberarem a flag para o resto da base.

Poderíamos ter tentants para QA/homolog mas o foco (por enquanto) não é esse

2

Ótimo post, fiquei curioso pra saber mais sobre as feature flags, como são gerenciadas, se depois que a feature é ativada, a flag é deletada, etc.

2

As flags continuam existindo mesmo após ir pra produção, já que pode ser que em algum momento a gente precise desligar a feature pra todos ou só para aquela conta em específico