John Calistro, mentor de carreira em tecnologia, defende que em 2026 a senioridade deixou de ser medida pela velocidade de entrega e passou a ser medida pela qualidade das decisões que o dev ajuda o sistema a tomar.
Por muito tempo, ser sênior significou ser o executor mais rápido do time. Quem pega a task mais cabeluda, destrava o colega travado, revisa os PRs e entra no incidente quando ninguém mais sabe por onde começar.
Isso continua valendo. Só ficou pequeno.
O sistema que a gente mantém hoje não é mais um backend conversando com um banco. É uma malha de APIs consumidas por gente que você nunca viu, eventos trafegando entre times, dados alimentando decisão de diretoria e, agora, agentes de IA chamando ferramentas com permissões que alguém precisou definir. Nesse cenário, o maior valor de um sênior está em melhorar as decisões do sistema, e não em fechar mais cards.
Esse é o argumento de John Calistro num texto recente sobre o tema. Concordo com a tese e quero levar a conversa um pouco mais fundo: como isso aparece no código, nos contratos, nos agentes de IA e, principalmente, em como provar esse impacto quando ele não vira entrega visível. A provocação de partida é simples: se a única diferença entre um pleno e um sênior no seu time é quantos cards cada um fecha por sprint, a empresa está pagando caro por velocidade e desperdiçando o resto.
A fábrica de features e a métrica fácil demais de medir
A pressão por entrega transformou muito time em linha de montagem. O backlog vira esteira, a sprint vira unidade de produção e o sênior passa a ser avaliado por throughput: histórias entregues, bugs fechados, PRs revisados.
Essas métricas não são inúteis. São fáceis de contar. O problema é que o impacto mais caro de um sênior costuma aparecer como algo que deixou de acontecer, e o que não aconteceu não entra em relatório nenhum.
| O que aparece no relatório da sprint | O que quase nunca aparece |
|---|---|
| Histórias entregues | A integração frágil que não foi para produção |
| PRs revisados | O contrato de API corrigido antes de ganhar consumidores |
| Bug crítico resolvido rápido | A abstração precipitada que ninguém precisou desmontar seis meses depois |
| Feature com IA no ar | O agente que não recebeu permissão de escrita onde não devia |
| Dashboard novo publicado | A métrica que ganhou dono e definição antes de chegar na diretoria |
A coluna da direita é difícil de medir. Mas é justamente nela que a senioridade fica estratégica.
Transformar pedido vago em decisão
Problema real não chega pronto. Chega como pedido vago, urgência mal explicada, requisito que contradiz outro requisito e, muitas vezes, com a solução já escolhida antes de alguém entender o problema.
O sênior que faz diferença não começa perguntando "o que eu implemento?". Ele começa por outras perguntas:
- Que problema, exatamente, estamos resolvendo?
- Quem é afetado por isso, e quem é afetado se der errado?
- O que acontece se fizermos do jeito mais simples possível?
- E se fizermos com engenharia demais?
- O que aqui é decisão de produto e o que é restrição técnica?
- Que risco estamos aceitando, e quem sabe disso?
Um exemplo hipotético, mas que todo mundo já viu alguma versão: chega o pedido "precisamos exportar os relatórios em Excel, é urgente". Executado ao pé da letra, vira uma lib de geração de planilha, um endpoint novo e um job pesado rodando no horário de pico. Com três perguntas (quem usa, para quê, com que frequência), às vezes descobre-se que a pessoa exporta tudo só para filtrar por região, um filtro que a tela simplesmente não tem. O card "exportar Excel" vira o card "adicionar filtro por região", que custa uma fração do esforço e resolve o problema de verdade.
É isso que significa reduzir ambiguidade. Um sênior que transforma confusão em decisão acelera o time inteiro, mesmo na semana em que escreveu pouco código.
Contratos são onde a dívida técnica costuma nascer
Calistro faz uma observação que eu acho a mais forte do texto: sistemas modernos são, em boa parte, sistemas de contratos. Contrato entre APIs, entre serviços, de dados, de eventos, entre produto e tecnologia. E os mais perigosos são os contratos implícitos entre times, aqueles que ninguém nomeou e que só aparecem quando alguém quebra.
A forma mais comum de contrato fraco é a interface que promete mais do que deveria. Existe uma observação clássica de engenharia de software, conhecida como Lei de Hyrum: com usuários suficientes, todo comportamento observável do seu sistema vai virar dependência de alguém, esteja ele documentado ou não. Traduzindo para o dia a dia: se a sua API devolve um campo, alguém vai usar esse campo.
Veja um endpoint em FastAPI que serializa o modelo inteiro do banco:
# Antes: o contrato é "o que estiver na tabela hoje"
@app.get("/clientes/{cliente_id}")
def obter_cliente(cliente_id: int, db: Session = Depends(get_db)):
cliente = db.get(Cliente, cliente_id)
return cliente.to_dict() # inclui flags internas, score de risco, campos legados...
Funciona. Passa no teste. E no dia em que alguém criar uma coluna observacao_interna na tabela, ela vai sair na resposta da API sem ninguém decidir isso. Pior: se algum consumidor começar a ler o score_risco, você nunca mais vai conseguir remover essa coluna sem quebrar alguém.
# Depois: o contrato é explícito e versionável
class ClienteOut(BaseModel):
id: int
nome: str
email: EmailStr
criado_em: datetime
@app.get("/clientes/{cliente_id}", response_model=ClienteOut)
def obter_cliente(cliente_id: int, db: Session = Depends(get_db)):
return db.get(Cliente, cliente_id)
A diferença de código é pequena. A diferença de decisão é enorme: agora existe uma promessa escrita, e mudar a tabela não muda a API por acidente.
Com eventos, vale o mesmo raciocínio. Um evento que muda de formato sem aviso derruba consumidores que você talvez nem saiba que existem. O mínimo é carregar o tipo e a versão no próprio envelope, para que o consumidor consiga decidir o que fazer com cada formato:
{
"tipo": "pedido.criado",
"versao": 2,
"ocorrido_em": "2026-11-08T13:00:00Z",
"dados": {
"pedido_id": "a81f...",
"valor_total": 349.90,
"moeda": "BRL"
}
}
Nenhum desses exemplos é sofisticado. O ponto é que o sênior precisa enxergar o contrato antes de ele virar dependência, e isso exige perguntas que vão além da implementação local:
- Quem consome isso hoje, e quem pode passar a consumir?
- O que essa interface promete, de forma explícita e implícita?
- O que quebra se a gente mudar?
- Quem é o dono?
- Como esse contrato vai envelhecer?
Em sistema complexo, proteger contrato é proteger a capacidade de evoluir.
Decidir sob restrição
Senioridade não é saber a resposta certa em abstrato. É saber decidir com prazo, orçamento, time e contexto reais. Quase toda decisão relevante é um trade-off, e o sênior não é quem escolhe sempre a arquitetura mais elaborada, nem quem escolhe sempre a mais simples. É quem entende o contexto o suficiente para justificar a escolha e assumir as consequências.
Uma forma prática de pensar é perguntar, para cada trade-off, que sinal no contexto puxa a decisão para um lado ou para o outro:
| Trade-off | Pende para o primeiro quando | Pende para o segundo quando |
|---|---|---|
| Velocidade × manutenção | É um experimento com data para morrer | O código está no caminho crítico e vai durar anos |
| Simplicidade × flexibilidade | O requisito ainda está instável | As variações já foram comprovadas por uso real |
| Autonomia × governança | Time pequeno, impacto contido | Dado sensível, regulação ou muitos consumidores |
| Distribuição × coesão | Escala e ritmo de deploy realmente diferentes entre partes | O domínio ainda está sendo descoberto |
| Consistência × disponibilidade | Envolve saldo, estoque, dinheiro | Contadores, feeds, recomendações |
| Automação × controle | A ação é reversível e de baixo impacto | A ação é irreversível ou mexe com dado de cliente |
A tabela não substitui o julgamento, mas obriga a decisão a ter um porquê. E os exemplos que Calistro usa mostram bem o tipo de raciocínio que separa o sênior do executor:
- Talvez o sistema não precise de microsserviços agora, e sim de fronteiras de domínio melhores (escrevi sobre isso em monolito modular vs microsserviços).
- Talvez a API não precise de GraphQL, e sim de uma resposta REST mais bem desenhada.
- Talvez o dashboard não precise de mais uma ferramenta de BI, e sim de um contrato de dados claro.
- Talvez o agente de IA ainda não deva executar nada, só sugerir com revisão humana.
- Talvez a métrica técnica esteja verde enquanto a jornada do usuário está degradada.
Nada disso cabe num card do Jira. Mas muda o destino do sistema.
Agentes de IA são o trade-off mais novo da lista
Dos exemplos acima, o do agente merece atenção especial, porque é onde muito time está tomando decisão de contrato sem perceber. Quando um agente pode chamar ferramentas, cada ferramenta exposta é uma permissão concedida. "O agente tem acesso à API de pedidos" não é um contrato, é um cheque em branco.
O mínimo razoável é tornar explícito o que o agente pode fazer sozinho, o que ele só pode sugerir e o que está fora do alcance dele:
FERRAMENTAS = {
"consultar_pedido": {"modo": "executar", "escopo": "leitura"},
"emitir_reembolso": {"modo": "sugerir", "escopo": "escrita"},
# "excluir_cliente" simplesmente não existe para o agente
}
def despachar(nome: str, args: dict, usuario: str):
regra = FERRAMENTAS.get(nome)
if regra is None:
raise PermissionError(f"Ferramenta não permitida para o agente: {nome}")
registrar_auditoria(ferramenta=nome, args=args, solicitante=usuario)
if regra["modo"] == "sugerir":
# vai para uma fila de aprovação humana em vez de executar
return fila_revisao.enfileirar(nome, args, solicitante=usuario)
return executar(nome, args)
É uma lista de permissões com três estados e um registro de auditoria. Não é engenharia de ponta. Mas alguém precisa parar e perguntar "o que acontece se o modelo chamar emitir_reembolso com o argumento errado?", e esse alguém, num time saudável, é o sênior.
Dívida consciente ou complexidade empurrada para frente
Todo sistema envelhece. A diferença é como.
Alguns envelhecem com clareza: módulos bem separados, contratos explícitos, decisões registradas e caminhos razoáveis de evolução. Outros envelhecem por acúmulo: o endpoint temporário que virou permanente, o job sem dono, o dado sem definição, a permissão ampla demais que ninguém lembra por que foi dada, o fluxo que ninguém consegue explicar de ponta a ponta.
O sênior não consegue impedir toda dívida técnica, e nem deveria tentar. O papel dele é separar a dívida que vale contrair da dívida que só adia o problema. Calistro resume isso numa pergunta que eu gostaria de ver em toda reunião de refinamento:
"Estamos fazendo uma concessão consciente ou apenas empurrando complexidade para o futuro?"
John Calistro
A palavra-chave é consciente. Dívida consciente tem três características: alguém decidiu, alguém sabe por quê e alguém sabe quando ela precisa ser paga. Se falta uma das três, não é concessão, é esquecimento com prazo indeterminado.
A ferramenta mais barata que conheço para tornar essa consciência explícita é o ADR (Architecture Decision Record): um arquivo curto, versionado junto com o código, que registra uma decisão e o contexto em que ela foi tomada. Não precisa de ferramenta especial. Um markdown na pasta docs/adr resolve:
# ADR-014: Exportação de relatórios via job assíncrono
## Status
Aceita (2026-11-03)
## Contexto
Relatórios acima de 50 mil linhas estouram o timeout do gateway.
Usuários precisam do arquivo, não da resposta imediata.
## Decisão
Gerar o arquivo em job assíncrono e notificar por e-mail com link
de download válido por 24h.
## Consequências
- Positivas: request não bloqueia, gateway deixa de estourar.
- Negativas: usuário espera alguns minutos; mais um job para monitorar.
- Dívida assumida: sem fila com prioridade por enquanto.
Revisar se o volume diário passar de X exportações.
Repare na última seção. A dívida está ali, com nome e com gatilho de revisão. Daqui a um ano, quem abrir esse arquivo vai entender que o atalho foi uma escolha, e não um descuido.
Como tornar visível o impacto que não vira card
Aqui está o ponto em que muita discussão sobre senioridade para no discurso. Calistro lista sinais melhores de impacto do que volume de entrega: decisões técnicas melhoradas, ambiguidade reduzida, riscos antecipados, retrabalho evitado, contratos mais claros, incidentes prevenidos, revisões mais profundas, documentação de decisões críticas, evolução de outros devs e redução de acoplamento desnecessário.
Concordo com a lista. O problema é que, na avaliação de desempenho, "reduzi ambiguidade" sem evidência soa como desculpa de quem entregou pouco. Impacto invisível só conta quando você deixa um rastro dele. Para cada sinal, existe um artefato concreto que pode servir de prova:
| Sinal de impacto | Evidência que dá para apontar |
|---|---|
| Decisão técnica melhorada | ADR escrito ou revisado, com alternativas descartadas |
| Ambiguidade reduzida | História reescrita com critério de aceite claro; escopo cortado antes do desenvolvimento |
| Risco antecipado | Comentário de PR ou issue que levantou o problema antes do deploy |
| Contrato mais claro | Schema versionado, OpenAPI atualizado, response model explícito |
| Incidente prevenido | Alerta ou métrica de observabilidade criada antes da feature crítica ir ao ar |
| Evolução de outros devs | Revisões que explicam o porquê, pareamentos, padrões que o time passou a seguir sozinho |
| Acoplamento reduzido | Dependência removida, módulo que passou a ser testável isoladamente |
Isso não é abandonar a entrega. Código continua importando. O que muda é a pergunta da avaliação: deixa de ser só "quanto essa pessoa entregou?" e passa a incluir "quanta clareza, segurança e direção técnica ela gerou?".
Amplitude sem perder profundidade
O contexto atual pede um sênior mais transversal. Não especialista em tudo, mas capaz de conversar com várias dimensões do sistema: arquitetura, produto, operação, segurança, dados, integrações, experiência do usuário, IA e automação, custo e manutenção.
Essa amplitude não substitui profundidade técnica. Ela dá contexto para a profundidade ser bem aplicada. O sênior que só enxerga o código local consegue otimizar uma parte e piorar o todo: a query que ficou dez vezes mais rápida e passou a segurar lock numa tabela que outro serviço usa, o cache que melhorou a latência e quebrou a consistência que o financeiro esperava.
Influência sem cargo
Tem um último ponto do texto que considero subestimado. O sênior, na maioria das vezes, não é gestor, não é o arquiteto oficial e não tem a palavra final. Mesmo assim, precisa influenciar a decisão.
Influenciar não é mandar, nem ganhar discussão. É construir clareza suficiente para que a melhor decisão fique fácil de tomar. Na prática, isso passa por apresentar alternativas com custo e consequência lado a lado, em vez de defender uma opção só; por escrever antes de discutir, porque um documento curto organiza melhor a conversa do que uma reunião de uma hora; e por saber discordar sem transformar a discussão em disputa de ego.
O sênior que sabe muito mas não consegue elevar a decisão do grupo tem impacto limitado. O sênior que ajuda o time a pensar melhor multiplica o próprio impacto.
Checklist de autoavaliação
Calistro propõe cinco perguntas para quem é sênior ou está caminhando para isso. Acrescentei a cada uma o tipo de evidência que ajuda a responder com honestidade, sem cair no "acho que sim":
- Que decisão importante ajudei a melhorar recentemente? Não basta ter entregue a task: a decisão ficou melhor por causa da sua participação? Procure um ADR, uma thread ou um PR em que o rumo mudou.
- Que risco antecipei antes de virar incidente? Senioridade aparece muito na prevenção. Procure o alerta que você pediu, a validação que você exigiu, o deploy que você segurou com um bom motivo.
- Que contrato técnico ficou mais claro por minha influência? API, evento, dataset, módulo, permissão, responsabilidade entre times. Algum deles ganhou dono, versão ou definição?
- Que ambiguidade reduzi para o time? Alguma discussão confusa terminou com um caminho claro porque você fez as perguntas certas?
- Que parte do sistema ajudei a envelhecer melhor? Talvez a pergunta mais importante da lista, porque desloca a senioridade do curto prazo para a sustentabilidade.
Se você travou em três ou mais, não significa que você não é sênior. Pode significar que está sendo usado como pleno rápido, ou que o impacto existe mas não está deixando rastro. Nos dois casos, vale mudar alguma coisa.
Pra fechar
Ainda precisamos de gente que escreve bom código, resolve problema difícil e entrega software funcionando. Isso não mudou. O que mudou é que, sozinho, isso não define mais o valor de um sênior.
O sênior que importa em 2026 é o que melhora decisões, reduz ambiguidade, protege contratos, antecipa riscos e ajuda o sistema a envelhecer bem. Menos fábrica de features, mais decisão de sistema. E, de preferência, com rastro suficiente para que alguém consiga enxergar isso na hora da avaliação.
