DEV Community

Cover image for PARE DE USAR POST EM TUDO, JOVEM! (E Descubra o Superpoder da Idempotência)
Daniel Camucatto
Daniel Camucatto

Posted on

PARE DE USAR POST EM TUDO, JOVEM! (E Descubra o Superpoder da Idempotência)

Introdução: O Guardião dos Dedos Nervosos



Você já tentou fazer uma compra online e a página travou? Seu dedo (ansioso) disparou o clique duas, três, quatro vezes no botão "Finalizar Compra". O que acontece?

Em um sistema mal projetado, você poderia ter sido cobrado três vezes e seu extrato bancário seria um pesadelo. Em um sistema robusto, isso não acontece. O que impede a catástrofe? Idempotência.

A Idempotência (sim, o nome parece um feitiço arcano) é um conceito fundamental na matemática, trazido para a Engenharia de Software para resolver um problema simples e brutal da computação distribuída: a rede não é confiável!

Definição Simples:

Uma operação é Idempotente se você puder executá-la múltiplas vezes, com os mesmos parâmetros, e o resultado final no sistema for exatamente o mesmo que seria após a primeira execução.

Pense no interruptor de luz:

Ação: Ligar a luz.

Idempotente? Sim. Se a luz já está acesa, pressionar o interruptor novamente não muda o estado (a luz continua acesa).

A Idempotência, portanto, é a sua rede de segurança contra timeouts, falhas de conexão e, principalmente, contra os Dedos Nervosos dos seus usuários. Ela garante a consistência e a integridade dos dados do seu sistema.

Meio: A Idempotência é Maior que o Pagamento



Quando falamos em Idempotência, o primeiro (e mais óbvio) exemplo é o sistema de pagamentos. É onde a falha custa dinheiro. Mas este superpoder arquitetural se aplica a qualquer área crítica de escrita de dados no seu sistema.

A Idempotência é o alicerce de sistemas distribuídos e Arquiteturas Orientadas a Eventos, onde a repetição de mensagens é a regra, não a exceção.

Casos de Uso Críticos (Além de Pagamentos)



Processamento de Mensagens/Estoque:



Um microsserviço de pedidos envia um evento "Pedido Confirmado". O serviço de estoque consome essa mensagem e dá baixa no inventário. Se, por falha de rede ou retry, o serviço de estoque consumir a mesma mensagem duas vezes, você acaba de perder dois itens do seu inventário por um erro de comunicação. A Idempotência resolve isso.

Criação de Contas/Tickets:


Um formulário de contato cria um ticket de suporte (POST /tickets). O usuário clica "Enviar", vê que está demorando e clica novamente. Sem Idempotência, sua equipe terá que lidar com três tickets idênticos.

Comunicações Externas:


Se um job de processamento falha e é repetido, a idempotência garante que o e-mail de "Parabéns, seu pedido foi enviado!" seja despachado apenas uma vez e não a cada 5 minutos até que o job finalmente termine com sucesso.

Design de API: O Superpoder Nativo do PUT



A beleza do protocolo HTTP (que define o estilo REST) é que ele já especifica quais métodos são idempotentes.

Método HTTP Propriedade Uso Recomendado
GET Idempotente & Seguro Apenas leitura.
DELETE Idempotente Remover um recurso. Remover duas vezes tem o mesmo efeito final (ele some).
PUT Idempotente Substituir/Atualizar um recurso. Atualizar com os mesmos dados 50 vezes resulta no mesmo estado final.
POST NÃO Idempotente Criar um novo recurso. Repetir 50 vezes cria 50 novos recursos.

O seu primeiro passo para uma API mais robusta é usar o PUT sempre que sua intenção for substituir ou redefinir o estado de um recurso conhecido.

Discussão de Métodos: PARE DE USAR POST EM TUDO, JOVEM!



O principal pecado das APIs "não-RESTful" é o uso excessivo e incorreto do POST.

Muitos desenvolvedores, por pressa ou desconhecimento, usam POST para criar e atualizar, transformando endpoints em "caixas pretas" não idempotentes. O resultado é um API frágil que não consegue se recuperar de simples falhas de rede.

❌ Quando NUNCA usar POST (se puder evitar)

Você não deve usar POST para atualização completa se for possível usar PUT.

Cenário de Atualização com PUT (Idempotente)

Se você precisa mudar o nome de um usuário de ID 123, e você envia todo o objeto do usuário, use PUT:

// Requisição
// PUT /usuarios/123
// Body: { nome: "Novo Nome", email: "novo@email.com",...}

// Resultado da 1ª Chamada: O usuário 123 é atualizado.
// Resultado da 2ª Chamada: O usuário 123 permanece com "Novo Nome". ✅ IDEMPOTENTE!

Enter fullscreen mode Exit fullscreen mode

O Perigo do POST (Não-Idempotente)



O POST deve ser reservado para cenários onde a intenção é criar um novo recurso e o servidor é responsável por gerar o identificador (ID).

// Requisição
// POST /usuarios
// Body: { nome: "Fulano de Tal", email: "fulano@tal.com"}

// Resultado da 1ª Chamada: Cria usuário com ID=1.
// Resultado da 2ª Chamada: Cria usuário com ID=2. ❌ NÃO IDEMPOTENTE!

Enter fullscreen mode Exit fullscreen mode

⚠️ Alerta de Solução Front-End (Não é Idempotência!)

Muitos times implementam soluções no front-end para "resolver" o problema do duplo clique:

  1. Desabilitar o botão imediatamente após o primeiro clique.

  2. Redirecionar para uma tela de processamento sem o botão de ação.



Isso é um paliativo, não uma solução.


Por quê? O front-end é completamente inseguro. Se o usuário estiver usando o aplicativo no celular e perder a conexão Wi-Fi (o famoso "buraco de rede") após o primeiro clique, o navegador pode tentar o retry da requisição sem que o usuário clique novamente. Além disso, um atacante mal-intencionado pode ignorar seu código JavaScript e enviar a requisição HTTP diretamente.

A Idempotência é uma responsabilidade do back-end. O front-end pode ajudar na UX, mas o back-end deve ser robusto o suficiente para lidar com requisições duplicadas vindas de qualquer fonte.

O POST Crítico: Como Aplicar a "Chave de Idempotência"



No entanto, há cenários críticos (como a criação de pedidos ou pagamentos) onde o POST é semanticamente correto (você está criando algo), mas a idempotência é obrigatória.

Nesses casos, a solução é o uso do Idempotency-Key (Chave de Idempotência), um header HTTP que funciona como um bilhete único para aquela operação de negócio.

Exemplo em TypeScript (Pseudo-código do Servidor)

// Pseudo-código TypeScript no servidor (exemplo simples)
// Requisição: POST /api/pagamentos
// Header: Idempotency-Key: 1a2b3c-pedido-456-ts

import { Request, Response } from 'express';

async function processarPagamento(req: Request, res: Response) {
  const idempotencyKey = req.headers['idempotency-key'] as string;
  const dadosPagamento = req.body;

  // 1. Verificar o Cache/Banco de Dados
  // Substitua 'cache.get' por uma consulta ao seu DB/Cache
  const resultadoSalvo = await cache.get(idempotencyKey);

  if (resultadoSalvo) {
    // 2. Chave Encontrada! Retornar o resultado original sem re-executar.
    console.log(`Chave ${idempotencyKey} já processada. Retornando resultado em cache.`);
    return res.status(200).send(resultadoSalvo);
  }

  // 3. Chave Nova! Executar a lógica de negócio (o pagamento real)
  const transacao = await servicoPagamento.processar(dadosPagamento);

  // 4. Armazenar a Chave e a Resposta para futuras repetições.
  // TTL: Time To Live (Tempo de vida) da chave, para limpeza automática
  await cache.set(idempotencyKey, transacao, { ttl: '24h' });

  // 5. Retornar a resposta (201 Created)
  return res.status(201).send(transacao);
}

Enter fullscreen mode Exit fullscreen mode

Neste fluxo, se o cliente enviar a mesma requisição com a mesma Idempotency-Key por causa de uma falha, o servidor irá interceptar no passo 2 e devolver o resultado da primeira operação, garantindo que o pagamento ocorra apenas uma vez.

Conclusão: Um Sistema Mais Sólido e uma Comunidade Melhor



A Idempotência não é um detalhe elegante. É um requisito de design para construir sistemas resilientes e confiáveis.

O primeiro passo é respeitar a semântica HTTP: use PUT para atualizações completas e DELETE para remoções.

E para os cenários críticos de criação (POST), assuma a responsabilidade e implemente a Chave de Idempotência. Sua equipe e seus usuários agradecem. Uma API idempotente é sinônimo de previsibilidade, consistência e menos chamados de suporte.

E você? Qual é o endpoint mais crítico do seu sistema que precisa de uma Chave de Idempotência urgente? Compartilhe este artigo com aquele colega que usa POST até para buscar dados! Vamos juntos construir um mundo com menos inconsistências e mais APIs que funcionam de primeira.

Top comments (0)