Idempotencia
Endpoints de mutación pueden aceptar el headerIdempotency-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/PATCHcuyo 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:- HTTP-level cache (tabla
idempotency_keys): para mutaciones genéricas. La response cruda del primer 2xx queda guardada y se replay en reintentos. - Database-level UNIQUE (
domain_events.event_id): específico de/public/events/ingest. LaIdempotency-Keyse hashea a UUID y va al campoevent_idUNIQUE — el mismo evento no se insert dos veces aunque pase tiempo.
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.