bhussainshoots
03/13/2026, 1:59 AMwait_time = (2^attempt) * random(0.5, 1.5) seconds. After 5 failures, trip the circuit and route to a dead-letter queue.
In n8n: Use the Error Trigger node separate from your main flow. Capture execution ID, timestamp, and error stack. Don't just log to console—write to a dedicated "failures" table in Postgres with retry counters.
In Activepieces: Branch on HTTP status codes. 429 (rate limit) → wait 60s → retry. 401/403 → immediate alert to Slack (credentials dead). 5xx → retry with backoff. Never retry 4xx client errors—that's just burning compute.
Idempotency keys:
For webhook-triggered flows (Stripe payments, form submissions), generate uuidv5(domain + payload_hash) as idempotency key. Store in Redis with 24h TTL. Prevents double-charging when webhooks retry aggressively.
The "poison pill" problem:
One malformed JSON in a batch of 1000 records kills the entire run. Use the "Continue on Fail" pattern with validation gates. JSON schema validation (ajv) at entry, filter invalid records to a quarantine branch before processing.
Monitoring: Alert on error rate velocity, not absolute count. 10 errors/hour is normal. 10 errors in 5 minutes means upstream API degradation.
What's your worst production failure? Mine was a timezone bug that triggered 3,000 duplicate emails at 2 AM because I used Date.now() instead of UTC normalization.