Definición
Una operación es idempotente cuando ejecutarla varias veces produce el mismo resultado que ejecutarla una sola vez.
Suena a tecnicismo abstracto y es lo que separa un sistema que puede reintentar con tranquilidad de uno que duplica pedidos cada vez que la red parpadea.
El ejemplo que lo aclara todo:
- «Pon el saldo a 100 €» es idempotente. Lo repitas las veces que lo repitas, el saldo queda en 100.
- «Suma 100 € al saldo» no lo es. Repetido tres veces, has sumado 300.
Por qué es un problema real
Porque en una red, no saber si algo salió bien es el caso normal, no la excepción.
Un cliente pulsa «Confirmar pedido». La petición llega al servidor, el pedido se crea, y justo entonces se corta la conexión antes de que llegue la respuesta. El cliente ve un error y vuelve a pulsar.
Sin idempotencia, ahora hay dos pedidos. Y el cliente no ha hecho nada mal: desde su lado, el primer intento falló.
Lo mismo con los reintentos automáticos. Un webhook que no recibe confirmación reintenta —así están diseñados—, y si tu endpoint no es idempotente, cada reintento crea un registro nuevo.
Los verbos HTTP y su promesa
En REST los verbos vienen con una promesa de idempotencia:
| Verbo | ¿Idempotente? |
|---|---|
| GET | Sí — leer no cambia nada |
| PUT | Sí — reemplaza con un estado concreto |
| DELETE | Sí — borrado dos veces sigue borrado |
| POST | No — crea algo nuevo cada vez |
Por eso POST es donde se duplican las cosas, y es justo el verbo con el que se crean pedidos, pagos y registros.
Cómo se resuelve: la clave de idempotencia
El patrón estándar, y el que usan las pasarelas de pago serias:
- El cliente genera un identificador único para esa intención concreta y lo manda en la petición.
- El servidor, antes de hacer nada, comprueba si ya procesó esa clave.
- Si es nueva: ejecuta, guarda el resultado asociado a la clave y responde.
- Si ya existía: no ejecuta nada y devuelve el mismo resultado de la primera vez.
El detalle que se pasa por alto: la clave la genera el cliente al abrir el formulario, no el servidor al recibirlo. Si la generase el servidor, cada reintento traería una clave distinta y no serviría de nada.
Y hay que guardar la respuesta, no solo marcar la clave como usada. El segundo intento tiene que recibir el mismo pedido, no un «ya existe» que el cliente no sepa interpretar.
Ejemplo práctico
Donde más caro sale no tenerlo es en pedidos y cobros.
Un portal de cliente en el que confirmar un pedido es un POST sin protección duplica pedidos con una regularidad sorprendente: conexiones móviles inestables, gente que pulsa dos veces porque «no pasaba nada», pestañas recargadas. Y un pedido duplicado no es un registro de más: es mercancía preparada, servida y facturada dos veces, con la llamada del cliente que viene detrás.
Lo que aprendí: deshacer un duplicado siempre cuesta más que prevenirlo. Anular un pedido ya servido implica abono, recogida, ajuste de stock y una conversación incómoda. La clave de idempotencia son unas pocas líneas.
Y la trampa más común al implementarlo: pensar que basta con desactivar el botón en el navegador. Eso evita el doble clic y no evita nada más — ni la recarga, ni el reintento del móvil, ni la petición repetida por otra vía. La protección tiene que estar en el servidor; lo del botón es cortesía visual.
En integraciones que reciben webhooks pasa lo mismo con otra cara: el emisor reintenta por diseño, así que el receptor tiene la obligación de tolerar repeticiones. Ahí la clave suele venir dada — el identificador del evento — y basta con guardarlo y comprobarlo.
Errores comunes
- Confiar en desactivar el botón como única protección.
- Que la clave la genere el servidor. Entonces cada reintento es distinto.
- Marcar la clave como usada sin guardar la respuesta.
- No caducar las claves. Se acumulan; unas horas o unos días suelen bastar.
- Suponer que los webhooks llegan una sola vez. Llegan las que hagan falta.
- Usar POST para algo que en realidad reemplaza un estado. Si encaja un PUT, sale gratis.
- Reintentar en el cliente sin idempotencia detrás. Es multiplicar el problema.
Cuándo aplicarlo
Siempre que la operación cree algo, mueva dinero, envíe algo o consuma stock. Y siempre en cualquier endpoint que reciba webhooks o llamadas de un sistema que reintenta.
La pregunta que lo decide en un segundo: si esta petición llega dos veces, ¿qué pasa? Si la respuesta es «se duplica», necesitas idempotencia antes de ponerlo en producción.