Problem: Receiving duplicate webhook eventsSolution: Implement idempotency with event tracking
JavaScript
Python
HTTPie
Copy
// Track processed eventsconst processedEvents = new Map();app.post('/webhooks/sessions', async (req, res) => { const payload = req.body; // Create unique event ID const eventId = `${payload.event}_${payload.session.id}_${payload.timestamp}`; // Check if already processed if (processedEvents.has(eventId)) { return res.json({ status: 'duplicate' }); } // Process event await processWebhook(payload); // Mark as processed (keep for 1 hour) processedEvents.set(eventId, Date.now()); // Cleanup old entries const oneHourAgo = Date.now() - 3600000; for (const [id, timestamp] of processedEvents.entries()) { if (timestamp < oneHourAgo) { processedEvents.delete(id); } } res.json({ status: 'received' });});
Copy
from datetime import datetime, timedelta# Track processed eventsprocessed_events = {}@app.post("/webhooks/sessions")async def handle_webhook(request: Request): payload = await request.json() # Create unique event ID event_id = f"{payload['event']}_{payload['session']['id']}_{payload['timestamp']}" # Check if already processed if event_id in processed_events: return {"status": "duplicate"} # Process event process_webhook(payload) # Mark as processed (keep for 1 hour) processed_events[event_id] = datetime.now() # Cleanup old entries cutoff = datetime.now() - timedelta(hours=1) processed_events = { k: v for k, v in processed_events.items() if v > cutoff } return {"status": "received"}
Copy
# Webhook handler would be on your server# This shows how to test idempotency# First requesthttp POST https://your-server.com/webhooks/sessions \ event=session.created \ session:='{"id":"123"}' \ timestamp=1234567890# Duplicate request (should return duplicate status)http POST https://your-server.com/webhooks/sessions \ event=session.created \ session:='{"id":"123"}' \ timestamp=1234567890
Use a database or Redis for event tracking in production instead of in-memory storage for better reliability across multiple server instances.