Symptom
Events are moved to the dead letter queue (DLQ) after only 4 retries instead of the configured 5. Merchants expect 5 retry attempts before giving up, but Dispatch gives up one attempt early.
What you know
Dispatch retries failed webhook deliveries with exponential backoff. When all retries are exhausted, the delivery is moved to the dead letter queue for manual inspection.
The configuration says MAX_RETRIES = 5, meaning 5 retry attempts should execute before moving to DLQ. But only 4 retries actually happen.
The retry scheduler is called after each failed attempt. It increments the attempt number and checks if retries are exhausted.
Retry Flow
Initial delivery (attempt 0) → FAIL
→ scheduleRetry(attempt=0, maxRetries=5)
→ nextAttemptNumber = 1, 1 < 5 → retry ✓
Retry 1 (attempt 1) → FAIL
→ scheduleRetry(attempt=1, maxRetries=5)
→ nextAttemptNumber = 2, 2 < 5 → retry ✓
...
Retry 3 (attempt 3) → FAIL
→ scheduleRetry(attempt=3, maxRetries=5)
→ nextAttemptNumber = 4, 4 < 5 → retry ✓
Retry 4 (attempt 4) → FAIL
→ scheduleRetry(attempt=4, maxRetries=5)
→ nextAttemptNumber = 5, 5 >= 5 → DLQ! ← but retry 5 never ran!
Hints
TypeScript
TypeScript ready
Test Output
▶
Click "Run Tests" to execute your code