¿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 |
|---|---|---|
| GET | Sí | Lee un recurso — llamado N veces devuelve los mismos datos, sin cambio de estado |
| HEAD | Sí | Como GET pero solo headers |
| PUT | Sí | Reemplaza un recurso — llamado N veces deja el recurso en el mismo estado final |
| DELETE | Sí | Remueve un recurso — N veces: la primera lo remueve, las siguientes son no-ops |
| OPTIONS | Sí | Descubrir métodos permitidos |
| TRACE | Sí | Loopback diagnóstico |
| POST | No | Crea un recurso — llamado N veces típicamente crea N recursos |
| PATCH | No (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
- Recibe request con idempotency key.
- Chequea el key store (Redis, tabla DB) por entrada existente.
- Si encontrada: devuelve la response guardada (sin side effects).
- Si no encontrada: adquiere un lock en la key, procesa el request, guarda la response, libera el lock.
- Maneja in-flight requests: si llega un duplicado mientras el primero procesa, espera o devuelve 409 Conflict.
- 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.
Herramientas LoadFocus relacionadas
Lleva este concepto a la práctica con LoadFocus — la misma plataforma que potencia todo lo que acabas de leer.