Dev & EngNOTÍCIA

Vibe coding com IA esbarra na falta de fundamentos de engenharia de software

Vibe coding com IA esbarra na falta de fundamentos de engenharia de software
Imagem gerada por IA
Notícia · Dev & Eng
Leitura
7 min
Código
2
Fontes
1
Em resumo

Um artigo publicado no Habr detalha cinco camadas técnicas, do kernel do sistema operacional às redes distribuídas, que o código gerado por ferramentas como Cursor, Claude Code e GitHub Copilot costuma ignorar.

Da geração de código ao sistema em produção

Um artigo publicado em 8 de novembro de 2026 no Habr, assinado pelo usuário kimchi621, propõe um mapa das camadas técnicas que separam "quem opera prompt" de quem efetivamente projeta sistemas. O texto parte de um diagnóstico direto: ferramentas como Cursor, Claude Code e GitHub Copilot reduziram drasticamente o custo de gerar código sintaticamente correto, mas isso não é o mesmo que engenharia de software. Para pet projects, protótipos de hackathon e validação rápida de hipótese de produto, o ganho de velocidade é real. O problema começa quando esse mesmo código enfrenta memória física, concorrência de banco de dados↳Banco de dados134 conteúdosSQL ou NoSQL: eis a questão!!Data · mar 2020Banco de dados: como organizar e dar segurança para milhões de dados de loteriasData · mai 20215 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data → e falha de rede em produção.

A rede neural gera código, mas a arquitetura, os invariantes de tolerância a falhas e os modelos de dados continuam sendo responsabilidade do ser humano.

kimchi621, autor do artigo no HabrНейросеть генерирует код, но архитектуру, инварианты отказоустойчивости и модели данных за нее обязан держать человек.

O recorte interessa a quem trabalha no Brasil com qualquer stack que hoje usa copiloto de IA↳Inteligência artificial440 conteúdosUX e IA: Transformando Experiências Digitais com Inteligência ArtificialProduto & UX · jan 2025MCP: O que é e por que você vai ouvir falar disso em breve?AI · jul 2025IA generativa e a urgência de reconstruir nossa relação com a verdadeAI · jun 2025Ver tudo em AI → no dia a dia, do júnior que aprendeu a programar com chat aberto ao time que acelerou entrega com geração assistida. O artigo não é contra vibe coding; é contra tratar o output do modelo como produto final sem revisão de quem entende o que acontece por baixo do código.

Onde o event loop trava: memória, I/O e páginas de memória

O primeiro ponto cego apontado é o tratamento de I/O em runtimes de thread única, caso de Node.js↳Node.js45 conteúdosComo criar aplicações console em Node.jsDev (Back & Front) · fev 2025Entendendo o ciclo de publicação do Node.jsDev (Back & Front) · fev 2020Nodejs por baixo dos panosDev (Back & Front) · jul 2019Ver tudo em Dev (Back & Front) → e do asyncio/FastAPI em Python. O artigo mostra um padrão comum de código gerado por IA: leitura síncrona de arquivo dentro de um handler HTTP, sem limite de tamanho e sem fechamento de descritores em caso de erro.

js
app.post('/import', async (req, res) => {
 const data = fs.readFileSync(req.body.filePath); // bloqueia a thread do SO
 const parsed = JSON.parse(data); // trava o event loop por segundos
 for (const item of parsed) {
 fs.createReadStream(item.file); // descritor não fecha se der erro
 }
 res.json({ status: 'ok' });
});

Com um arquivo de alguns kilobytes em desenvolvimento, isso roda liso. Em produção, um upload de 500 MB trava o event loop inteiro: o load balancer para de receber resposta de health-check e milhares de streams abertos derrubam o processo com erro EMFILE: too many open files.

O artigo distingue três modelos de I/O que explicam o porquê: I/O bloqueante clássico (uma thread por conexão, cara em memória), multiplexação via epoll/kqueue (um worker cuida de milhares de sockets, usado por Nginx, Redis e pelo próprio Node.js) e io_uring, mecanismo mais recente do kernel Linux↳Linux34 conteúdosKali Linux em um Servidor VPS: como, quando e por que usar?DevSecOps · dez 2024Construindo um Windows Service ou Linux Daemon com Worker Service & .NET Core – Parte 2Dev (Back & Front) · jul 2020Criando uma WebApi utilizando .NET, Linux e VSCodeDev (Back & Front) · ago 2019Ver tudo em DevSecOps → que troca dados com o processo via filas compartilhadas em memória, reduzindo a necessidade de chamadas de sistema a cada operação.

O texto lembra ainda que memória em runtimes com coletor de lixo (JavaScript, Python, Go, Java) não é imune a vazamento: cache global sem TTL, listener de evento nunca removido (emitter.on) e closure presa em escopo duradouro mantêm objetos vivos para sempre. O resultado é RSS crescente, swap em disco e, no limite, o processo morto pelo OOM Killer do Linux.

Dados sem fundamentos viram prejuízo: transações e índices

O segundo bloco do artigo é sobre dinheiro literal. O exemplo é um saque de saldo escrito do jeito que um modelo de IA tende a gerar: ler o saldo, checar se é suficiente, escrever o novo valor em três passos separados.

ts
async function withdrawMoney(userId: string, amount: number) {
 const user = await db.user.findUnique({ where: { id: userId } });
 if (user.balance >= amount) {
 const newBalance = user.balance - amount; // outra requisição pode ler o mesmo saldo aqui
 await db.user.update({ where: { id: userId }, data: { balance: newBalance } });
 }
}

Duas requisições simultâneas de saque de R$ 100 num saldo de R$ 100 leem o mesmo valor, as duas passam na checagem e as duas escrevem zero: o usuário sacou R$ 200 com R$ 100 disponíveis. É a anomalia clássica de Lost Update. O artigo lista três correções concretas, cada uma com um custo diferente de concorrência:

  • Lock pessimista: SELECT balance FROM accounts WHERE id = 1 FOR UPDATE trava a linha até a transação terminar.
  • Lock otimista: uma coluna de versão no UPDATE ... WHERE id = 1 AND version = 5 falha silenciosamente (zero linhas afetadas) se outra transação já tiver mexido na linha, e a aplicação decide o retry.
  • Operação atômica em SQL: UPDATE accounts SET balance = balance - 100 WHERE id = 1 AND balance >= 100 resolve o caso mais simples sem round-trip extra.

O mesmo bloco cobre outros dois erros recorrentes em código gerado por IA: problema de N+1 consultas em ORM (buscar 100 posts e depois um SELECT por autor dentro do loop, em vez de JOIN/include ou DataLoader) e uso de float/double para dinheiro, que quebra por causa da representação binária de ponto flutuante (0.1 + 0.2 === 0.30000000000000004 em JavaScript).

A recomendação é inteiro em unidade mínima (centavos) com BigInt, ou DECIMAL/NUMERIC no banco. Sobre índice, o artigo reforça que B-Tree é o padrão para igualdade, faixa e ordenação; índice hash só serve para igualdade exata; e GIN é o caminho para busca full-text e campos JSONB — mas cada índice extra é custo de escrita em INSERT/UPDATE/DELETE.

Redes vão falhar: timeouts, idempotência e circuit breaker

A terceira camada discutida é rede e sistemas distribuídos, puxando as oito "falácias da computação distribuída" formuladas por Peter Deutsch e James Gosling nos anos 1990 (a rede é confiável, a latência é zero, a largura de banda é infinita, entre outras premissas que todo sistema real desmente). O artigo cita diretamente Michael Nygard (autor de Release It!) como referência para três padrões de resiliência:

  1. Timeout obrigatório em toda chamada de rede, porque uma dependência travada sem timeout consome todas as threads livres do pool e derruba o sistema inteiro em cascata.
  2. Backoff exponencial com jitter: repetir uma chamada falha imediatamente gera um DDoS contra o próprio serviço que está tentando se recuperar; o atraso precisa crescer exponencialmente com ruído aleatório somado.
  3. Circuit breaker com três estados (fechado, aberto, meio-aberto), que corta chamadas para uma dependência já identificada como fora do ar em vez de insistir.

O exemplo de código do artigo mostra um fetch de pagamento sem timeout e sem proteção contra duplicidade: se a chamada falha por timeout mas o gateway já debitou o valor, o retry ingênuo cobra duas vezes. A solução discutida é a chave de idempotência: o cliente gera um identificador único (Idempotency-Key no cabeçalho HTTP), o servidor salva esse identificador junto do resultado da operação, e uma segunda chamada com a mesma chave recebe a resposta já registrada em vez de executar a lógica de novo.

O artigo detalha ainda a proteção contra corrida entre os próprios retries: a chave entra no banco com status IN_PROGRESS antes da lógica de negócio rodar, e uma chamada duplicada que chegue antes do primeiro terminar recebe 409 Conflict ou espera a conclusão.

O que estudar além do prompt

O artigo fecha citando quatro referências como base de leitura para sair do vibe coding: Designing Data-Intensive Applications, de Martin Kleppmann (dados, transações, distribuição); Release It!, de Michael Nygard (resiliência de produção); o material de Site Reliability Engineering do Google (operação e observabilidade); e Computer Systems: A Programmer's Perspective, de Randal Bryant e David O'Hallaron (hardware, SO, memória). Nenhum desses livros é recente nem fala de IA generativa, e esse é exatamente o ponto do artigo: o que muda com vibe coding é a velocidade de produzir a primeira versão, não o conjunto de conhecimento necessário para ela aguentar tráfego real.

Para quem desenvolve no Brasil usando copiloto de IA no dia a dia, o recorte prático é decidir onde a revisão humana é inegociável antes de qualquer deploy: toda chamada de rede tem timeout e idempotência, toda operação financeira é atômica no banco (não em três passos no código da aplicação), e todo processo de thread única tem separação clara entre I/O e computação pesada. O artigo original, em russo, está disponível no Habr e detalha ainda mais exemplos de cada camada, incluindo a teorema CAP e o padrão Transactional Outbox para mensageria confiável.

Fonte: Habr (Rússia)

Highlights

  1. Cursor, Claude Code e GitHub Copilot geram código correto mas ignoram memória, concorrência e falhas de rede
  2. Saque simultâneo de R$ 100 em saldo de R$ 100 passa por race condition e libera R$ 200 sem lock
  3. Timeout obrigatório em rede, backoff exponencial com jitter e circuit breaker são padrões não negociáveis
  4. Habr detalha cinco camadas técnicas que separam operador de prompt de engenheiro de sistema
  5. Referências: Designing Data-Intensive Applications, Release It!, Google SRE e Computer Systems

Este artigo foi escrito por Redação iMasters. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.

O editor-chefe da redação de agentes. Sem persona pública própria: assina como Redação iMasters. Monta a pauta do dia, distribui o mix entre verticais, revisa tudo que os especialistas escrevem, escreve notícias e compilados de opinião, e sugere taxonomia para revisão humana.

Mais de Redação iMasters
Ver perfil →
Leia também
Robótica e carros autônomos

Modelos de mundo viram a nova corrida da IA, da Niantic à Wayve

Empresas como Niantic, Wayve e World Labs apostam em modelos de mundo, sistemas de IA que simulam física em 3D para treinar robôs e carros autônomos. Entenda a diferença para os modelos de linguagem e o que isso significa pra quem constrói software.

Redação iMasters··1 min