10 Erros de API REST Que Estão Sabotando Seu Backend (E Como Corrigir Cada Um)
Voltar para o blog
Backend

10 Erros de API REST Que Estão Sabotando Seu Backend (E Como Corrigir Cada Um)

Status code errado, N+1 escondido, resposta gigante, falta de idempotência, log com dado sensível... Listei os 10 erros que mais vejo em code review de APIs Spring Boot — cada um com o impacto real em produção e a correção prática, pronta para aplicar.

5 min de leitura
3 views
27 de setembro de 2026
Compartilhe
Compartilhar:LinkedInXWhatsAppFacebook

Depois de anos revisando APIs em produção — de startups a sistemas governamentais — percebi que os mesmos erros aparecem em todo lugar. Não são erros de iniciante: são armadilhas que o tempo, a pressa e o acúmulo de código impõem em qualquer time, inclusive nos maduros.

Aqui estão os 10 que mais causam incidente, cada um com o impacto real e a correção direta. Use como checklist no seu próximo code review.

Erro 1: Retornar 200 com mensagem de erro no body

O clássico dos clássicos. A API responde 200 OK com um corpo tipo {"success": false, "error": "Pedido não encontrado"}. Parece inofensivo, mas quebra toda a cadeia de observabilidade: monitores, gateways, balanceadores e caches tratam a resposta como sucesso. Seu dashboard fica verde enquanto o usuário recebe erro na tela.

Correção: use o status code correto, sempre. 400 para validação, 404 para recurso inexistente, 409 para conflito de estado, 422 quando a semântica pedir. O status code é o primeiro contrato da sua API — quem consome precisa confiar nele.

Erro 2: N+1 escondido atrás do ORM

Um endpoint de lista que faz 1 query para buscar os registros + N queries para cada relacionamento acessado. Com 50 registros, são 51 roundtrips no banco. Em produção, com 500 registros e latência de rede, esse endpoint vira o mais lento do sistema — e ninguém sabe por quê, porque em desenvolvimento com 5 registros tudo parece rápido.

Correção: fetch join ou @EntityGraph no Spring Data JPA para os relacionamentos que a resposta usa. E monitore o SQL gerado em desenvolvimento: habilite logging de queries e trate qualquer endpoint que dispara mais de 3 queries por requisição como suspeito.

Erro 3: Resposta sem paginação

GET /pedidos retornando 80 mil registros em JSON. Derruba o servidor em três frentes: estoura a memória do heap, satura a rede e trava o cliente que tentou parsear tudo. É o erro que mais gera OOM em produção.

Correção: paginação obrigatória em toda coleção, com limite máximo forçado no servidor — nunca confie no page size que o cliente manda. Se o cliente pede size=100000, o servidor responde com o máximo permitido. E para exports grandes, o padrão é job assíncrono com download, não endpoint síncrono.

Erro 4: DTO vazando a entidade

Retornar a entidade JPA direto no controller expõe campos internos, cria loop de serialização em relacionamentos bidirecionais, dispara lazy loading em momentos inesperados e acopla o contrato da API ao schema do banco. Mudou uma coluna? Quebrou o app mobile.

Correção: DTOs explícitos, sempre. Cada endpoint define exatamente o que expõe. O MapStruct elimina o boilerplate de mapeamento — o custo inicial de criar DTOs é muito menor que o custo de desacoplar contrato de schema depois.

Erro 5: Validação só no frontend

O frontend valida, o backend confia. Um curl de 3 linhas burla tudo: dados inválidos entram no banco, regras de negócio são violadas, e o pior cenário — injeção e abuso — fica em aberto.

Correção: Bean Validation no controller (@Valid + constraints nos DTOs) para o formato, e regras de negócio na camada de domínio para a semântica. A divisão conceitual é: o frontend valida para experiência do usuário; o backend valida por segurança. Um não substitui o outro.

Erro 6: PUT que não é idempotente

PUT tem contrato semântico: chamado 2 vezes, produz o mesmo resultado. Se seu PUT incrementa estoque, acumula pontos ou gera evento a cada chamada, ele é um POST disfarçado — e qualquer retry de rede (que acontece o tempo todo) duplica o efeito.

Correção: PUT substitui o estado completo do recurso. Operações com efeito acumulativo merecem endpoint próprio com idempotency key: o cliente gera um identificador único por operação, e o servidor garante que a mesma key não executa duas vezes. É assim que sistemas de pagamento funcionam.

Erro 7: Versionamento inexistente

A API quebra o app mobile em produção porque ninguém versionou. O app já está publicado na loja, o usuário não pode ser obrigado a atualizar, e agora você precisa manter compatibilidade retroativa em código que nunca foi desenhado para isso.

Correção: versionar desde o dia 1 (/v1/) mesmo que "não precise". O custo de criar /v2/ quando chegar a hora é zero se /v1/ existir desde o início — e infinito se não existir. Mudança de contrato sem nova versão é incidente agendado.

Erro 8: Erros sem estrutura padronizada

Cada endpoint retorna o erro de um jeito: um usa "message", outro "error", outro "detail", com estruturas aninhadas diferentes. O frontend vira um if-else gigante, o time de suporte não consegue mapear erros, e o log vira adivinhação.

Correção: RFC 7807 (Problem Details for HTTP APIs) com um @ControllerAdvice global. Um contrato único de erro para toda a API: type, title, status, detail e detalhes específicos quando fizer sentido. Uma hora de configuração que economiza meses de atrito.

Erro 9: Timeout e retry sem política

Chamada entre serviços sem timeout definido espera para sempre — e cada requisição pendente segura recursos, até esgotar o pool. Retry sem backoff, por outro lado, martela o serviço que já está sofrendo, transformando uma degradação em queda total (o efeito cascata clássico de microserviços).

Correção: timeout explícito em todo cliente HTTP, dimensionado pelo p99 do serviço chamado — não por chute. Retry com exponential backoff e jitter apenas em operações idempotentes. E circuit breaker (Resilience4j) nas chamadas críticas, para falhar rápido e proteger o próprio serviço.

Erro 10: Logar dados sensíveis

Payload com CPF, senha, token ou dados de cartão indo inteiro para o log. O log vai para o sistema de observabilidade, que tem retenção longa e acesso amplo — e você acabou de criar um vazamento de dados dentro da própria infraestrutura. Em setores regulados, isso é passível de sanção.

Correção: mascaramento estruturado no logging (filtros que ofuscam campos sensíveis antes da serialização), nunca logar o body completo de requisições autenticadas, e revisão periódica do que está sendo efetivamente escrito nos logs. Log deve contar a história do incidente sem expor o usuário.

O checklist para o próximo code review

Status codes corretos? Paginação com limite forçado? DTO explícito? Validação no backend? Idempotência nos métodos que prometem? Timeout e retry com política? Log limpo de dados sensíveis? Se os 7 passaram, sua API já está à frente da maioria em produção.

Qual desses erros você já pegou em produção? Comenta aí — e se tiver um erro que não entrou na lista, melhor ainda: compartilha para a comunidade aprender. Os comentários desse post viram material do próximo.

nexucodeplay
Autor do artigo

nexucodeplay

Desenvolvedor Fullstack

Especialista em Java, Spring Boot, React, Flutter e arquitetura moderna de software.

Perguntas frequentes

Dúvidas comuns sobre o tema

Sim. Esse conteúdo aborda tecnologias e conceitos amplamente utilizados no mercado moderno de desenvolvimento.

Publicidade

Apoie o projeto acessando nossos parceiros.

Publicidade
Compartilhe

Curtiu esse conteúdo?

Compartilhe este artigo com outros desenvolvedores e ajude mais pessoas a evoluírem na carreira.

Continue estudando

Artigos relacionados

Conteúdos profissionais sobre arquitetura, backend moderno, frontend e performance.

Deixe seu comentário

Compartilhe sua opinião sobre este conteúdo.

Deixe um comentário

Comentários passam por moderação para evitar spam e manter a qualidade.

Comentários

Ainda não existem comentários.