Pular para o conteúdo
← artigos
atualizado Spec-Driven DevelopmentVibe CodingAI AgentsAI CodingSoftware Engineering

Spec-Driven Development vs. vibe coding: uma comparação honesta de quem usa os dois

Vibe coding é real e útil. Também é a escolha errada para tudo que precisa estar correto. Um RCT do METR, um duelo de idempotência em pagamentos e o veredito honesto.

Vibe coding é real, funciona e eu uso. Mas ele tem um modo de falha que fica mais caro quanto mais capaz o modelo fica. Este artigo é a comparação honesta: o que é cada abordagem, onde cada uma quebra e a regra para decidir quando usar qual.

Se você está chegando agora em SDD, a metodologia completa está em O que é Spec-Driven Development?. Depois volte aqui para o confronto direto.

O que vibe coding é, de fato

Andrej Karpathy cunhou o termo num post no X em 2 de fevereiro de 2025. A descrição dele era precisa: você se entrega totalmente às vibes, abraça os exponenciais e esquece que o código sequer existe. Você não está escrevendo código. Está descrevendo uma intenção e aceitando o que o modelo produz. O nome é certeiro. Você programa no feeling.

Quando apresentou a ideia, Karpathy limitou explicitamente o vibe coding a projetos descartáveis de fim de semana. Esse limite importa. O próprio criador nunca propôs o vibe coding como metodologia de produção. Em menos de um ano, ele virou outra coisa: o jeito padrão como a maioria dos devs usa ferramentas de AI coding. O nome pegou, e a restrição original caiu pelo caminho sem ninguém notar.

O workflow tem três passos. Você descreve o que quer em linguagem natural. O modelo gera o código. Você dá um empurrão quando algo parece errado e gera de novo. Você não lê cada linha. Você conduz uma conversa. Quem dirige é o modelo.

É um trabalho genuinamente útil. Num protótipo descartável, você põe algo de pé em vinte minutos. Num script quebrado, três prompts costumam resolver. Para entender a cara real de um problema antes de se comprometer com uma arquitetura, vibe coding dá um ciclo de feedback rápido que nada mais oferece.

A pergunta não é se vibe coding funciona. É onde ele deixa de ser seguro.

O problema estrutural que vibe coding não resolve

Vibe coding otimiza para o momento em que algo roda pela primeira vez. Terminal verde. Uma página que renderiza. Uma função que retorna um valor. Esse momento parece progresso. A confiança do modelo é contagiosa.

A sensação começa a mentir no instante em que o trabalho precisa sobreviver à sessão. A IA vive num eterno presente. Cada conversa começa do zero: nenhuma lembrança da restrição que você adicionou às 22h, do edge case que você pensou no banho, da regra de negócio que você deixou num comentário e depois apagou. Tudo o que você não escreveu é reinventado. E não do mesmo jeito.

Não é um problema que espera um contexto maior para ser resolvido. Uma context window de um milhão de tokens diz ao agente o que o sistema é hoje. Não diz nada sobre o que ele deveria se tornar: sua intenção, suas restrições, os edge cases que importam para você, o que está fora de escopo de propósito. Uma janela maior deixa o agente mais bem informado sobre o presente e nem um pouco mais sábio sobre o alvo.

A formulação de Addy Osmani mostra onde fica o teto: a IA te leva a uns 70% do caminho, rápido. Os últimos 30% são onde mora o código de produção: edge cases, regras de negócio, invariantes, restrições de segurança, tudo o que não é óbvio no caminho feliz. Vibe coding não tem nenhum mecanismo de precisão nessa profundidade. Ele manda outro prompt e torce para o modelo preencher a lacuna direito.

Às vezes preenche. Muitas vezes, não. Você só descobre qual dos dois quando o código encontra algo real.

A spec é o que fornece a direção que o modelo não consegue inventar.

Os dados são piores do que você imagina

O que a pesquisa encontrou de fato

19%
mais lentos com IA (resultado real)RCT do METR, 2025, devs experientes nos próprios codebases
~20%
mais rápidos (o que acharam depois)Mesmos devs, mesmo estudo, conclusão errada
246
issues reais testadas16 devs experientes, projetos open source grandes e maduros
~40%
do código de IA sensível à segurança tinha uma vulnerabilidade conhecidaPearce et al., IEEE S&P 2023
Confiança não é competência. Devs experientes se sentiram mais rápidos enquanto estavam mais lentos.

Em 2025, o METR rodou um ensaio clínico randomizado com 16 devs open source experientes, trabalhando em 246 issues reais em codebases grandes e maduros, com modelos de fronteira: Cursor Pro com Claude 3.5 e 3.7 Sonnet. Os devs esperavam que a IA os deixasse 24% mais rápidos. Na prática, ficaram 19% mais lentos. E, depois, ainda acreditavam que ela tinha acelerado o trabalho em uns 20%.

Esse último número é o incômodo. A combinação de output confiante com erros invisíveis torna a perda de produtividade invisível de dentro da sessão. Você se sente rápido. Está mais lento. A distância entre as duas coisas é exatamente o que produz código errado-mas-confiante que vai para produção. (O METR publicou um follow-up no início de 2026 dizendo que modelos mais novos mostram resultados diferentes no estudo em andamento; os dados de 2025 continuam sendo a base de RCT mais rigorosa para aquela geração de ferramentas, e o mecanismo por trás não mudou.)

O quadro de segurança é um capítulo à parte. A pesquisa de Pearce et al., publicada no IEEE Security and Privacy, mostrou que cerca de 40% do código gerado em contextos sensíveis à segurança continha uma vulnerabilidade conhecida. O mecanismo importa mais que o número: em código gerado por IA, um defeito é uma lacuna na especificação. Essa lacuna volta toda vez que o código é regenerado, com outra cara, até uma spec codificar a restrição explicitamente.

A crítica fica mais desconfortável por um motivo específico: o problema piora à medida que os modelos melhoram. Um modelo mais fraco faz uma coisa pequena e obviamente errada. Um modelo capaz faz uma coisa grande, coerente, bem arquitetada e sutilmente errada. Capacidade amplifica a direção. Não a fornece.

Por que o mesmo bug sempre volta

Esse é o mecanismo que a maioria das comparações deixa passar, e é o argumento central a favor de trabalhar com spec.

Em código gerado por IA, um defeito não é um erro no código. É uma lacuna na especificação. Como a geração é não determinística, essa lacuna reaparece com outra cara toda vez que o código é regenerado, até uma spec codificar a restrição explicitamente. Você corrige o output. Não corrige o processo. A próxima regeneração traz a mesma classe de problema de volta, em outro formato.

Vibe coding não tem como fechar essa lacuna na origem. Cada correção é um ajuste local num output avulso. O agente começa cada sessão nova do zero, deduz a mesma premissa que faltava e produz a mesma classe de erro.

A solução não é um prompt melhor. É escrever a restrição num artefato durável a partir do qual o agente consiga executar. Escrever a spec é corrigir o processo em vez do output. Quando você corrige o processo, toda regeneração futura produz uma implementação segura automaticamente. Toda sessão começa da mesma base.

É por isso que o modo de falha é invisível de dentro da sessão. Você manda outro prompt, o problema some, o terminal fica verde. Parece resolvido. A lacuna continua aberta. Ela volta na próxima regeneração, na próxima mudança de contexto ou na próxima vez que outro agente mexer no mesmo código.

Um confronto concreto: a cobrança que cobra duas vezes

Pegue uma tarefa realista de porte médio: um endpoint de cobrança em que um retry do cliente nunca pode cobrar o cliente final duas vezes. Esse padrão aparece nos fluxos de pagamento que construí ao entregar, sozinho, uma fintech cripto de 13 apps em 70 dias. O estudo de caso tem os números completos.

O caminho do vibe: você escreve “crie um endpoint POST /v1/charges com idempotência”. O modelo gera sessenta linhas de handler em oito segundos. Parece completo. Não está. Idempotência exige estado: um registro de quais chaves já foram processadas. Sem uma constraint explícita no banco, dois retries concorrentes podem entrar em race condition, os dois leem “não encontrado” e os dois inserem uma cobrança nova. Cliente cobrado em dobro.

O caminho da spec escreve isto antes de existir qualquer código:

FR-1  WHEN a merchant POSTs a charge with a valid Idempotency-Key,
      THE SYSTEM SHALL create at most one charge for that (merchant_id, key) pair.
FR-2  WHEN the same Idempotency-Key is replayed within 24h,
      THE SYSTEM SHALL return the original charge and create no new one.

Data model:
  charges(id, merchant_id, amount_cents, idempotency_key, status, created_at)
  UNIQUE(merchant_id, idempotency_key)   -- this enforces FR-1 at the database level

A constraint UNIQUE é toda a diferença. Não é uma checagem no código que uma race condition consegue driblar. É uma invariante no nível do banco que o agente precisa implementar, e ela sobrevive a toda regeneração. A frase EARS (WHEN/SHALL) deixa o comportamento explícito o bastante para o modelo não inventar um atalho. Usei exatamente esse padrão em todos os endpoints de pagamento daquela fintech. Nenhum cobrou em dobro em produção.

Vibe coding

  1. 01Prompt: crie um endpoint de cobrança com idempotência. 60 linhas em 8 segundos.
  2. 02Chave de idempotência guardada numa coluna, mas sem constraint: retries concorrentes disputam e os dois inserem.
  3. 03A cobrança dupla aparece no teste de carga (na melhor hipótese) ou em produção (no caso comum).
  4. 04Um novo prompt corrige o sintoma, não a lacuna. Na próxima regeneração: a mesma classe de bug.
  5. 05Próxima sessão: o modelo começa do zero. Nenhuma memória da discussão sobre a restrição.

Spec-Driven

  1. 01Regra EARS escrita primeiro: WHEN a mesma chave é reenviada, THE SYSTEM SHALL devolver a cobrança original.
  2. 02UNIQUE(merchant_id, idempotency_key) declarada no modelo de dados antes de existir código.
  3. 03O agente gera o handler com o caso de concorrência coberto na primeira passada.
  4. 04A restrição vive na spec. Toda regeneração produz uma implementação segura.
  5. 05Próxima sessão: o agente lê a spec. A invariante já está lá.
Mesmo modelo. Mesma tarefa. Resultado diferente. A constraint UNIQUE é a única variável. Da fintech cripto de 13 apps que o Felipe construiu de verdade.

O caminho do vibe não é só mais lento no total. É mais lento de um jeito que você não enxerga até o código falhar. E falha de um jeito que volta toda vez que você regenera sem corrigir a spec.

Frente a frente no que importa

Vibe coding vs. Spec-Driven Development

Vibe coding vs. Spec-Driven Development. Winner: Spec-Driven with a weighted score of 51. Scale 1-5 (5 = best).
Critério (peso)Vibe codingSpec-Driven
Velocidade até o primeiro output (2)53
Correção em features reais (3)25
Custo de retrabalho (invertido: maior = menos retrabalho) (3)25
Escala além de uma sessão (3)15
Pontuação ponderada2551

Scale 1-5 (5 = best). Highlighted column: winner by weighted score.

Pesos para trabalho de produção. Em scripts descartáveis e protótipos de uma sentada, os pesos mudam. Ali, o vibe ganha no que importa.

Vibe coding lidera em uma única dimensão de produção: velocidade até o primeiro output. Essa vantagem encolhe quando você conta os ciclos de retrabalho. A velocidade até o output correto conta outra história.

Onde os métodos diferem no que conta

Vibe coding versus Spec-Driven Development, lado a lado

A spec não é overhead. É a correção do problema estrutural que vibe coding não resolve.
DimensãoVibe codingSpec-Driven
Artefato principalO último promptA spec aprovada
Memória entre sessõesNenhuma. Começa do zero toda vez.O arquivo da spec. O agente continua de onde você parou.
Garantia de correçãoO que o modelo deduziu do promptO que a spec diz explicitamente
Quando um defeito voltaOutro prompt e torcer. A lacuna na spec continua aberta.Atualizar a spec. A restrição fica selada para todas as execuções futuras.
Serve paraProtótipos, scripts, exploração numa sessão sóFeatures de produção, movimentação de dinheiro, compliance
A spec não é overhead. É a correção do problema estrutural que vibe coding não resolve.

A habilidade que falta aos devs seniores

A maioria dos devs chegou às ferramentas de IA com a intuição de que o gargalo era a velocidade de implementação. Se o modelo escreve código mais rápido, eu fico mais rápido. O resultado do METR derruba essa premissa sem rodeios. Devs experientes nos próprios codebases ficaram mais lentos. O gargalo nunca foi a implementação. Foi a precisão da intenção.

Isso pesa mais nos devs seniores do que qualquer um espera, e o motivo é contraintuitivo. Experiência significa mais contexto implícito: mais conhecimento da história do sistema, mais premissas sobre o que é “correto”, mais decisões que parecem óbvias e nunca são escritas. Todo esse conhecimento tácito é invisível para o modelo. Quanto mais você sabe, maior a distância entre o que você disse e o que você quis dizer.

Um dev júnior descreve o que quer em termos mais explícitos, porque tem menos certeza do que é óbvio. Um dev sênior passa um rascunho para o modelo e espera que ele complete o resto como outro engenheiro experiente completaria. O modelo não completa assim. Ele faz pattern matching contra tudo o que já viu, e o padrão mais comum não é o seu sistema específico.

É por isso que o resultado do METR atinge com mais força justamente quem mais esperava ganhar com a IA. Os devs do estudo eram experientes, trabalhavam nos próprios codebases e usavam modelos de fronteira. Mesmo assim, perderam terreno. A causa não é capacidade. É a distância entre o que foi dito e o que precisava ser verdade.

A própria orientação da Anthropic deixa isso explícito: “deixar o Claude pular direto para o código pode produzir código que resolve o problema errado”. Anos de experiência não te ajudam a escrever prompts mais rápido. Ajudam a pensar com precisão no que precisa ser verdade antes de o código rodar: as restrições, os edge cases, as invariantes, o que está fora de escopo de propósito. Essa precisão, trancada na sua cabeça, é invisível para o modelo. Escrever uma spec a externaliza num artefato durável a partir do qual o agente consegue executar de verdade.

Aprofundei isso em Don’t Code, Specify: por que devs experientes estavam tendo resultados piores com ferramentas de IA, e o que mudou quando troquei o workflow padrão.

O veredito honesto: vibe quando errar é barato, spec quando não é

Não estou argumentando contra vibe coding. Eu uso o tempo todo, e você deveria usar também. O erro é aplicá-lo à classe errada de problema.

A Anthropic traça uma linha prática na própria orientação: “se você consegue descrever o diff em uma frase, pule o plano”. Uso esse teste o tempo todo. Uma frase significa baixa complexidade, baixo risco, provavelmente pouco em jogo. Quando a descrição pede três frases e uma lista de edge cases, isso é a spec.

A maioria dos projetos reais precisa dos dois modos. Faça no vibe o trabalho exploratório, para entender qual é o problema de verdade. Especifique tudo o que vai para produção. O erro é tratar todo trabalho como de uma categoria só. É assim que surgem vibe coders com incidentes em produção e escritores de spec sem nada entregue.

A ideia dos 70% aponta onde fica a emenda. Use vibe coding para chegar aos 70% rápido e depois mude para SDD para fechar a lacuna direito. Em sequência, sem competição.

FAQ

Vibe coding é ruim?

Não. Vibe coding é genuinamente útil para trabalho de baixo risco e feedback rápido: protótipos, scripts, spikes exploratórios. O problema não é a abordagem. É aplicá-la a trabalho em que correção, edge cases e continuidade entre sessões realmente importam.

O modo de falha é tratar vibe coding como padrão para todo desenvolvimento assistido por IA, inclusive features de produção em que os últimos 30% de correção sustentam tudo.

Foi o Karpathy que inventou o vibe coding?

Andrej Karpathy cunhou o termo em 2 de fevereiro de 2025, num post no X. Ele descreveu a prática como se entregar totalmente às vibes e esquecer que o código sequer existe. O conceito em si (aceitar o output da IA sem ler cada linha, conduzindo no feeling) já vinha surgindo na prática; ele deu nome e forma.

Ele também limitou explicitamente a ideia a projetos descartáveis de fim de semana. Essa restrição original se perdeu conforme o termo se espalhou. A maior parte dos problemas de vibe coding em produção vem direto de ignorar o escopo que Karpathy definiu.

Dá para combinar vibe coding e SDD?

Dá, e na maioria dos projetos reais você deveria. Vibe coding é excelente para explorar: você aprende qual é o problema construindo uma versão tosca rápido. A spec captura o que você descobriu e vira a base do build de produção.

Vibe para descobrir. Spec para entregar. Em sequência, sem competição.

Por que o mesmo bug de IA sempre volta?

Porque você corrigiu o output, não a spec. Em código gerado por IA, um defeito é uma lacuna na especificação. A geração é não determinística, então essa lacuna reaparece com outra cara toda vez que você regenera, até uma spec codificar a restrição explicitamente.

A correção é ajustar a spec, não só o código. O código é o output. A spec é a fonte. Esse é o mecanismo central por trás da recorrência de vulnerabilidades em código de IA sensível à segurança (Pearce et al., IEEE S&P 2023).

Por que devs seniores ficam mais lentos com IA?

Dois motivos. Primeiro, devs experientes carregam mais contexto implícito, ou seja, mais premissas que o modelo pode violar em silêncio. A distância entre o que você quis dizer e o que você disse é maior quando seu modelo mental do sistema é complexo.

Segundo, devs experientes costumam trabalhar em sistemas de produção em que os últimos 30% de correção sustentam tudo. É exatamente aí que o vibe coding empaca. O resultado do METR (19% mais lentos nos próprios codebases, com modelos de fronteira) chama atenção porque esses devs conheciam bem seus codebases. O gargalo era a precisão da intenção, não a familiaridade com o código.

Para onde ir agora

Vibe coding e SDD respondem a perguntas diferentes. O vibe pergunta: quão rápido consigo pôr algo para rodar? O SDD pergunta: como garanto que o que está rodando é o que eu realmente quis construir?

As duas perguntas importam. A habilidade é saber qual delas se aplica.