¿Qué es Idempotencia? Métodos HTTP, API Keys, Ejemplos

Idempotencia: llamar a una operación N veces tiene el mismo efecto que una vez, crítico para retries seguros. GET/PUT/DELETE son idempotentes.

¿Qué es idempotencia?

Idempotencia es una propiedad de una operación donde ejecutarla múltiples veces produce el mismo resultado que ejecutarla una sola vez. En notación matemática: f(x) = f(f(x)) = f(f(f(x))). En contextos de APIs y sistemas distribuidos, una operación idempotente puede ser reintentada con seguridad sin causar side effects no intencionados, crítico cuando las redes son no fiables y no sabes si tu request anterior tuvo éxito.

El ejemplo clásico es un botón de elevador: presionarlo una o diez veces produce el mismo resultado (el elevador llega una vez). Compara con cobrar una tarjeta de crédito: presionar "pagar" diez veces sin idempotencia produce diez cargos. El diseño idempotente hace que los sistemas sean seguros para reintentar.

Idempotencia en APIs HTTP/REST

La especificación HTTP (RFC 7231) define qué métodos son idempotentes:

Método HTTP¿Idempotente?Uso típico
GETLee un recurso, llamado N veces devuelve los mismos datos, sin cambio de estado
HEADComo GET pero solo headers
PUTReemplaza un recurso, llamado N veces deja el recurso en el mismo estado final
DELETERemueve un recurso. N veces: la primera lo remueve, las siguientes son no-ops
OPTIONSDescubrir métodos permitidos
TRACELoopback diagnóstico
POSTNoCrea un recurso, llamado N veces típicamente crea N recursos
PATCHNo (por defecto)Update parcial, depende de semántica

Nota que idempotente NO significa "devuelve la misma response". DELETE devuelve 204 la primera vez y 404 en subsiguientes, responses diferentes, pero el estado del servidor es idéntico. La propiedad es sobre estado final, no equivalencia de response.

Ejemplos: idempotente vs no-idempotente

Operaciones idempotentes

  • PUT /users/123 {"name": "Alice"}, setea el nombre del user a Alice. Llamarlo 10 veces deja el nombre como Alice.
  • DELETE /sessions/abc, remueve session abc.
  • GET /products/42, lee producto 42.
  • PUT /flags/feature-x {"enabled": true}, toggle de feature flag por valor absoluto.

Operaciones no-idempotentes

  • POST /orders {...}, crea una nueva orden. 10 veces crea 10 órdenes.
  • POST /charges {...}, cobra una tarjeta. 10 veces cobra 10 veces.
  • PATCH /counters/x {"increment": 1}, incrementa por 1 cada call.
  • POST /emails {"to": "..."}, envía un email. 10 calls = 10 emails.

Por qué importa la idempotencia

En un mundo single-machine transactional, nunca llamarías la misma operación dos veces. Pero los sistemas modernos son distribuidos, y eso cambia todo:

  • Fallas de red. Tu cliente envía un request, no obtiene response. ¿Tuvo éxito? No sabes. Idempotente → reintentas con seguridad.
  • Timeouts. Mismo problema. El server puede haber procesado el request después que el cliente se rindió.
  • Reintentos distribuidos. Service meshes, load balancers y SDKs auto-reintentan. Solo seguro si upstream es idempotente.
  • Arquitecturas basadas en colas. Mensajes pueden ser entregados más de una vez (at-least-once). Consumers deben manejar duplicados idempotentemente.
  • Comportamiento de usuarios. Los usuarios doble-clickean botones submit, refrescan páginas mid-request.

Idempotency keys

Para operaciones naturalmente no-idempotentes como crear una orden o cobrar una tarjeta, el patrón estándar es la idempotency key: un identificador único generado por el cliente (típicamente UUID) enviado con cada request. El server registra el resultado indexado por este ID y devuelve el mismo resultado para cualquier request subsecuente con la misma key.

POST /charges
Idempotency-Key: 8e0a4e6b-1b8e-4e3a-b9f7-5e1d3f9c4b8a
{
  "amount": 5000,
  "currency": "USD"
}

El primer call procesa el cargo y guarda el resultado. Calls subsecuentes con la misma key devuelven el resultado guardado sin re-procesar. La key típicamente expira después de un window (ej. 24 horas).

Implementando idempotency keys server-side

  1. Recibe request con idempotency key.
  2. Chequea el key store (Redis, tabla DB) por entrada existente.
  3. Si encontrada: devuelve la response guardada (sin side effects).
  4. Si no encontrada: adquiere un lock en la key, procesa el request, guarda la response, libera el lock.
  5. Maneja in-flight requests: si llega un duplicado mientras el primero procesa, espera o devuelve 409 Conflict.
  6. Expira keys después del window acordado.

Ejemplos del mundo real

  • Stripe. La implementación de referencia. Cada endpoint API que cambia estado acepta un header Idempotency-Key.
  • AWS SDK. Muchas APIs AWS usan parámetros ClientToken (idempotency keys). EC2 RunInstances, RDS CreateDBInstance.
  • PayPal, Square, Adyen. Todos los procesadores de pago usan idempotency keys.
  • HTTP/2 + clientes retry-aware. Clientes HTTP modernos auto-reintentan métodos idempotentes en fallas de conexión.

Pitfalls comunes

  • Tratar PATCH como siempre idempotente. Depende de semántica.
  • Side effects más allá de la base de datos. Si tu endpoint "idempotente" envía un email, llamarlo dos veces envía dos emails.
  • Idempotency keys sin expiry. Almacenar cada key forever causa crecimiento ilimitado. Setea TTLs.
  • Race conditions en reintentos concurrentes. Usa locks o constraints DB.
  • Confundir idempotencia con safety. Safe = sin side effects (GET). Idempotente = N calls = efecto de 1 call. PUT/DELETE son idempotentes pero no safe.

Idempotencia en load testing

  • Endpoints POST acumulan estado. Un load test 1000-VU contra POST /orders crea 1000 × duración × rps órdenes. Cleanup después.
  • Reuso de idempotency key cachea la response. Si tu script reusa la misma key entre VUs, todos los VUs obtienen la response cacheada.
  • Genera idempotency keys únicas por VU/iteración.
  • Testea el mecanismo de idempotencia mismo.

FAQ: Idempotencia

¿Es GET siempre idempotente?

Por la spec HTTP, sí. GET nunca debería modificar estado. En la práctica, algunas APIs hacen mal uso de GET para cambios de estado.

¿Es PATCH idempotente?

Depende de la operación. PATCH {set: x} es idempotente. PATCH {increment: 1} no.

¿Cuál es la diferencia entre idempotencia y safety?

Safe significa sin side effects observables (GET, HEAD, OPTIONS). Idempotente significa N calls = estado final de 1 call. PUT y DELETE son idempotentes pero no safe.

¿Cómo hago POST idempotente?

Usa una idempotency key, un ID único generado por cliente (UUID) enviado con cada request.

¿Qué es un buen TTL de idempotency key?

Stripe usa 24 horas. Para APIs high-throughput, 1 hora puede ser suficiente. Para APIs de pago low-throughput, 7-30 días dan más tolerancia de retry.

¿Aplica idempotencia a gRPC y GraphQL?

Sí. Las definiciones de método gRPC pueden especificar nivel de idempotencia. Operaciones GraphQL Query son idempotentes por convención; Mutations necesitan diseño explícito de idempotencia.

Prueba LoadFocus para testear idempotencia at scale

Si estás diseñando un mecanismo de idempotencia y quieres verificarlo bajo carga (reintentos concurrentes, race conditions, expiry de keys), LoadFocus corre scripts JMeter y k6 desde 25+ regiones cloud con hasta 12.500 VUs. Regístrate en loadfocus.com/signup, sin tarjeta de crédito, y corre tu primer stress test de idempotencia en menos de 5 minutos.

¿Qué tan rápido es tu sitio web?

Mejora su velocidad y SEO sin problemas con nuestra Prueba de Velocidad gratuita.

Prueba de velocidad de sitio web gratis

Analice la velocidad de carga de su sitio web y mejore su rendimiento con nuestro comprobador de velocidad de página gratuito.

×