Durante 14 meses registramos cada webhook de Stripe en thMenu: 312 de 100.000 eventos llegaron con el mismo event_id dos o tres veces. Es la promesa "at-least-once delivery" de Stripe en cifras concretas — sin idempotencia, tres duplicados en tu libro de comisiones.
Por Qué El Mismo Evento Llega Tres Veces
Si Stripe no recibe respuesta 2xx en ~10 segundos, reintenta. Timeouts TCP, cold starts lambda, fallos DNS transitorios, incluso procesamiento exitoso seguido de caída de conexión — todo dispara retries.
Tres escenarios frecuentes: cold start Cloudflare Workers >10s, transacción D1 commiteada pero conexión cortada, o clic manual "resend" en el dashboard Stripe.
El Patrón INSERT-Claim
La defensa de thMenu es la tabla stripe_webhook_events con event_id PRIMARY KEY. Primera acción: INSERT. Error unique constraint 23505 = duplicado — 200 OK no-op.
Crítico: el claim debe preceder a la lógica de negocio para evitar race conditions.
Race Condition: Eventos Fuera de Orden
Incidente real: customer.subscription.updated llegó 800ms antes que checkout.session.completed. UPDATE afectó 0 filas. Fix: rollback del claim, devolver 503, Stripe reintenta.
FAQ
¿Verificar firma antes o después del claim? Antes. Verify es barato, escritura DB cara.
¿Cuánto tiempo retener filas de idempotencia? Stripe garantiza 30 días; nosotros mantenemos 90 días.
¿Stripe reintenta para siempre? No, máximo 3 días.
¿Te resultó útil? Compártelo.
Artículos relacionados
¿Qué es un menú QR? La guía completa para restaurantes
Un menú QR permite a tus clientes acceder a tu carta al instante desde el móvil,…
Pasar del menú en papel al menú QR digital: guía paso a paso
¿Quieres adoptar los menús QR pero no sabes por dónde empezar? Esta guía cubre f…
Menús QR geolocalizados: servir distintos idiomas según la IP del visitante
Cómo un resort de 180 plazas en Antalya enruta el mismo QR a menús turcos, alema…