Skip to main content

Idempotencia

Endpoints de mutación pueden aceptar el header Idempotency-Key para que reintentos del cliente (red flaky, timeout, retry automático) no causen efectos duplicados en el servidor.

Cuándo usarlo

  • Cualquier POST / PUT / PATCH cuyo efecto sea relevante (crear reserva, lanzar notificación, registrar evento).
  • En particular, POST /api/public/events/ingest — repetir la misma key con el mismo body es seguro.

Formato del header

  • Genera la key tú (UUID v4, hash determinístico, lo que tenga sentido para tu caller).
  • La misma key con el mismo body → segundo POST devuelve la respuesta cacheada del primero.
  • La misma key con un body distinto → 409 idempotency_key_in_use.
  • Sin header → endpoint procede normal (sin cache de idempotencia).

Ejemplo: ingest de eventos

Retención

Las keys se cachean 24 horas. Pasado ese tiempo, la key puede reutilizarse con un body distinto.

Implementaciones internas

Hay dos capas de idempotencia según el endpoint:
  1. HTTP-level cache (tabla idempotency_keys): para mutaciones genéricas. La response cruda del primer 2xx queda guardada y se replay en reintentos.
  2. Database-level UNIQUE (domain_events.event_id): específico de /public/events/ingest. La Idempotency-Key se hashea a UUID y va al campo event_id UNIQUE — el mismo evento no se insert dos veces aunque pase tiempo.
Para el caller son indistinguibles. Sólo necesitas saber: mismo key + mismo body = mismo id devuelto.

Patrón recomendado de retry

Qué NO hacer

  • ❌ Generar una key nueva en cada retry (defeats the purpose).
  • ❌ Reusar una key vieja con un body distinto (devuelve 409).
  • ❌ Asumir que una key es “consumida” tras un 2xx — sí lo está, pero el cache aún la sirve durante 24h.
  • ❌ Para idempotencia, NO uses el body field event_id (eliminado): usar siempre el header.