Inicio / Blog / Claves de idempotencia
Fiabilidad de API y sistemas distribuidos

Claves de idempotencia: reintentos seguros en integraciones reales

El cliente envía “crear pago”, la conexión expira y no sabe si hubo cobro. Reintentar sin identidad de operación puede duplicarlo; no reintentar puede dejar el pedido bloqueado. La clave permite al servidor reconocer que se repite la misma intención y devolver el resultado registrado.

Una intención, varios intentos de entrega

La clave permanece entre reintentos; una nueva acción recibe otra
1 / IntenciónEl cliente crea clave y petición canónica.
2 / EnviarEl servidor reserva la clave por ámbito.
3 / EjecutarMutación y resultado quedan persistidos.
4 / ReintentarLa misma clave devuelve el resultado anterior.

Idempotencia no significa “ignorar HTTP duplicado”. Es un contrato: para un ámbito y plazo definidos, la misma clave con la misma entrada produce un único efecto lógico y un resultado repetible. No garantiza entrega de red exactamente una vez ni hace atómicos efectos externos.

Diseña la clave alrededor de una operación

Genera una clave aleatoria cuando usuario o job crea la intención y persístela antes de enviar. UUID aleatorio suele bastar. No uses solo hora, ID de cliente o número del intento. Limita el ámbito por cuenta y operación. No permitas que una entrada no confiable cruce fronteras entre clientes.

Guarda una huella canónica de la solicitud. Reutilizar clave con importe, moneda o destino distinto debe producir conflicto, no repetir silenciosamente el resultado ni ejecutar otra mutación. Normaliza antes de calcular el hash y excluye campos de transporte que no cambian la intención.

Persiste reserva, efecto y respuesta coherentemente

EstadoSignificadoComportamiento del retry
NuevoNo hay operación para la clave y ámbito.Reservar atómicamente antes de ejecutar.
En cursoUna petición ejecuta y llega otra concurrente.Conflicto, Retry-After o espera corta documentada.
CompletadoEfecto y respuesta estable guardados.Devolver resultado anterior con la misma huella.
Fallido/inciertoFallo definitivo o efecto remoto sin confirmar.Clasificar y conciliar antes de otro efecto.

Usa restricción única en (ámbito, clave) para arbitrar concurrencia. Guarda estado, huella, respuesta o referencia y fechas. Si la mutación está en la misma base, registra negocio y resultado en una transacción. Para pagos o correo externos, usa también la clave del proveedor o un patrón outbox/conciliación: la transacción local no vuelve atómica una llamada HTTP remota.

Pago: timeout después del éxito remoto

El servicio crea `pedido-842:autorizar-v1` y envía. El proveedor autoriza, pero se pierde la respuesta. Repetir con la misma clave devuelve la autorización original; el servicio guarda la referencia y concluye. Un nuevo intento tras un rechazo deliberado o cambio de importe es otra intención, con clave y auditoría nuevas.

La semántica depende del proveedor. Algunos conservan la primera respuesta, incluso ciertos errores, y cada uno define una ventana de retención. Lee el contrato y conserva la clave local más que el periodo máximo de reintento y conciliación. Tras expirar la clave remota, consulta el estado antes de repetir un cobro incierto.

Webhook: entrega repetida, una transición

Guarda el ID de entrega con unicidad para deduplicar redelivery. También aplica idempotencia de dominio: actualiza una suscripción si la versión de origen es más nueva o la transición sigue siendo válida. El proveedor puede generar eventos distintos para el mismo objeto. Mantén intentos y efectos de negocio separados.

Job asíncrono: evita completar dos veces

Un mensaje puede volver tras caer el worker. Asigna ID estable al job, resérvalo atómicamente y vuelve idempotente cada acción posterior. Para varias etapas, registra estado y usa outbox/saga y compensaciones cuando corresponda. “Exactamente una vez” entre sistemas independientes suele ser una ilusión; apunta a entrega al menos una vez, efecto lógico único y conciliación.

Define la caducidad con criterio

Borrar claves pronto permite repetir una acción; guardarlas para siempre aumenta coste y obligaciones de privacidad. Define retención según retries de cliente, cola, dispositivos offline y soporte. Al borrar respuestas, conserva tombstone o unicidad de negocio cuando duplicar sea costoso. La caducidad forma parte del contrato de API.

Prueba los momentos ambiguos

Prueba misma clave/cuerpo secuencial y concurrente, cuerpo distinto, crash antes del commit, después del commit y antes de responder, timeout tras éxito remoto, caducidad y replay. Comprueba respuesta y número de efectos. Registra correlación y hash de clave, no payload sensible ni credenciales.

En resumen

La clave nombra una mutación pretendida en entregas inestables. Genérala una vez, limita su ámbito, vincúlala a una huella, resérvala con unicidad, persiste el resultado y entiende la retención del proveedor. Así el retry es recuperación, no apuesta a duplicar dinero o trabajo.

Referencias