Idempotencia en una consulta de infracciones
Un reintento por timeout no debería crear otro trabajo ni otro cargo. Qué garantiza una clave por operación, qué compara el servidor y por qué la respuesta puede cambiar igual.
Una integración envía la consulta de una patente y el servidor tarda en responder. El cliente corta por timeout y reintenta. Si cada intento crea un trabajo nuevo, esa falla de red acaba de duplicar el consumo de cupo, las alertas y quizá el cargo. Y si la respuesta se perdió en el camino de vuelta, el cliente ni siquiera sabe si el primer intento llegó.
La idempotencia es la propiedad que vuelve seguros esos reintentos: repetir el mismo pedido produce el mismo efecto que hacerlo una sola vez. En una API de infracciones importa porque los reintentos no son una anomalía a corregir; son el comportamiento normal de cualquier red.
Efecto no es lo mismo que respuesta
RFC 9110 define un método como idempotente cuando el efecto buscado de varios pedidos idénticos es igual al de uno solo. La definición habla del efecto sobre el servidor, no del contenido devuelto. Dos ejecuciones de la misma consulta pueden mostrar resultados distintos si un organismo cargó un acta entre una y otra. Eso no rompe la idempotencia: no se duplicó ningún trabajo, ningún cargo, ninguna notificación.
La distinción evita un malentendido frecuente: pedir idempotencia no es pedir que el dato quede congelado. Para comparar dos respuestas separadas en el tiempo hay que mirar las fechas de observación de cada una, no exigir que sean iguales.
Leer no es lo mismo que encargar
En HTTP, los métodos seguros como GET se definen como de solo lectura y por eso son idempotentes: reintentar una lectura no crea nada. Pero muchas consultas de infracciones no son una lectura directa. El cliente envía un POST que crea un trabajo asincrónico, porque la búsqueda recorre varias fuentes y tarda. POST no es idempotente por defecto: cada envío puede crear un trabajo nuevo, con su costo.
Ahí la idempotencia deja de ser una propiedad del método y pasa a ser una decisión de diseño del contrato.
Una clave que identifica la operación, no el dato
El patrón habitual es que el cliente genere una clave única por operación y la envíe junto con el pedido. El servidor registra esa clave en una operación atómica antes de crear el trabajo. Si la clave ya existe, no crea otro: devuelve el identificador del trabajo original o su estado actual.
Tres decisiones definen el contrato:
- la clave identifica la operación del cliente, no la patente: dos consultas legítimas del mismo dominio en momentos distintos llevan claves distintas;
- la ventana de retención es explícita: el servidor no recuerda claves para siempre, y el contrato dice cuánto;
- el nombre del encabezado y su alcance son convención documentada de esa API, no semántica universal de HTTP.
El error simétrico está del lado del cliente: generar una clave nueva en cada reintento. Para el servidor eso son operaciones distintas, y el mecanismo entero queda anulado.
La misma clave con otro cuerpo es un conflicto
Reusar una clave con un pedido diferente no debe resolverse eligiendo en silencio uno de los dos. Es un conflicto y merece un error explícito. RFC 9457 define un formato de detalles de problema con tipo, título y detalle que el cliente puede interpretar sin parsear texto libre, y que permite distinguir “clave reusada” de una falla transitoria.
Para decidir si dos cuerpos son el mismo pedido hace falta una comparación estable. Dos JSON pueden diferir en el orden de claves o en espacios y describir la misma consulta. RFC 8785 define una forma canónica de serialización que vuelve comparables esas variantes mediante un hash. Comparar bytes crudos también es válido, pero hay que documentarlo: un cliente que reordena claves entre reintentos vería conflictos que no entiende.
El resultado también viaja con identidad
La idempotencia no termina cuando el trabajo se crea. Si el resultado se comunica por webhook, el aviso puede reenviarse, y el consumidor necesita reconocer el duplicado. CloudEvents establece que la combinación de source e id identifica un evento: registrar esa dupla antes de ejecutar efectos permite descartar reenvíos, como desarrollamos en webhooks de nuevas multas.
Del lado del polling, preguntar por el estado de un trabajo existente es una lectura y puede repetirse sin riesgo; el ritmo y la revalidación tienen su propio contrato. Lo que no conviene repetir es el envío de la búsqueda completa para averiguar cómo sigue.
Qué verificar antes de integrar
Antes de poner reintentos automáticos en producción, verificá cuatro cosas del contrato:
- que el contrato distinga lecturas reintenables de operaciones que crean trabajos;
- que exista una clave por operación, con ventana de retención documentada;
- que el reuso de clave con otro cuerpo devuelva un conflicto explícito y legible por máquina;
- que los reintentos del cliente conserven la misma clave del primer intento.
Un reintento no debería ser una apuesta. Con la semántica correcta en cada método, una clave por operación y conflictos que se declaran en vez de resolverse en silencio, la falla de red vuelve a ser lo que es: un incidente de transporte, no una consulta duplicada.
Preguntas frecuentes
¿Idempotente significa que la respuesta será siempre la misma?
No. La idempotencia habla del efecto sobre el servidor, no del contenido de la respuesta. Dos ejecuciones legítimas de la misma consulta pueden devolver datos distintos si la fuente cargó o corrigió un acta entre una y otra. Lo que no debe duplicarse es el trabajo, el cargo o la notificación.
¿Reintentar un GET puede crear una consulta duplicada?
No debería. Los métodos seguros están definidos como de solo lectura, así que reintentarlos no crea nada. Si una API dispara trabajos con costo ante una lectura, se aparta de esa semántica y conviene tratar esa operación como si necesitara clave propia.
¿Qué pasa si reuso la clave con un pedido distinto?
Es un conflicto y el servidor debería rechazarlo con un error explícito, no elegir en silencio uno de los dos cuerpos. Un formato de error legible por máquina permite que el cliente distinga ese caso de una falla transitoria y no lo reintente a ciegas.
¿Cuánto tiempo debe recordar el servidor una clave usada?
Lo define el contrato de cada API. La ventana tiene que cubrir al menos el período razonable de reintentos del cliente; después puede expirar. Lo importante es que ese plazo esté documentado y no haya que descubrirlo en producción.
Fuentes consultadas 4 referencias
- RFC 9110 — HTTP Semantics (abre en una pestaña nueva) — RFC EditorConsultada el
- RFC 8785 JSON Canonicalization Scheme (abre en una pestaña nueva) — RFC EditorConsultada el
- RFC 9457 — Problem Details for HTTP APIs (abre en una pestaña nueva) — RFC EditorConsultada el
- CloudEvents specification (abre en una pestaña nueva) — Cloud Native Computing FoundationConsultada el
Datos y metodología
- Alcance de la nota
- Diseño del contrato de reintentos en una API de consultas de infracciones: métodos seguros, clave por operación, detección de conflictos y deduplicación del resultado. No cubre la validez jurídica de los datos consultados.
- Unidad de análisis
- Una operación de consulta y sus reintentos, identificados por una clave única definida por el cliente.
- Cobertura
- Semántica derivada de RFC 9110, RFC 8785, RFC 9457 y la especificación CloudEvents; la clave por operación se describe como convención de contrato, no como estándar publicado.
Limitaciones
- El nombre del encabezado de la clave y su ventana de retención varían entre APIs; la referencia es el contrato de cada proveedor.
- La comparación canónica aplica a pedidos, no a resultados; dos ejecuciones legítimas pueden devolver datos distintos.
- Los ejemplos son sintéticos y no describen la implementación interna de ningún portal oficial.
Fecha declarada del contenido: . La fecha de consulta no reemplaza la vigencia de la norma ni una revisión independiente.
Notas relacionadas
Webhooks de nuevas multas: idempotencia, reintentos y trazabilidad
Un webhook confiable puede llegar más de una vez, demorarse o fallar después de ser procesado. El diseño debe deduplicar eventos, reintentar con límites y conservar evidencia de punta a punta.
Polling de consultas de multas sin saturar la API: Retry-After y ETag
Consultar el estado cada segundo no hace que una búsqueda termine antes. Un contrato con Retry-After, ETag y una espera aleatoria reduce solicitudes repetidas, bytes y picos de clientes sincronizados.
Consultas largas de multas: cuándo responder 202 y exponer el estado
HTTP 202 confirma aceptación, no finalización. Una integración útil devuelve una operación consultable, transiciones explícitas, resultado parcial y una cancelación con semántica definida.