Deduplication
Why it matters
Since there are both in-process and persistent retries, the same event is expected to be received more than once. Without deduplication, the same invoice could be marked “aceptado” twice, duplicate emails could be sent, or business logic could run twice.
Mechanism
Each delivery includes two fields designed to detect repetition:
nonce— a unique identifier per delivery attempt (32 hexadecimal characters, 16 bytes).intento— the attempt number (1 to 5).
Use
nonceas the deduplication key, neverclaveornumero_consecutivo: the latter are repeated across attempts, because they belong to the document, not to the delivery.
Pattern
We recommend using a unique index in the DB so that deduplication is atomic: if the INSERT fails due to a collision, the event has already been processed and execution can end without affecting the rest of the flow.
async function procesarWebhook(evento) {
try {
await db.eventosLxs.create({
data: { nonce: evento.nonce, payload: evento, procesadoEn: new Date() }
});
} catch (err) {
if (err.code === 'P2002') { // unique constraint violation
// Already processed, discard
return;
}
throw err;
}
await aplicarLogicaDeNegocio(evento);
}