Retry Strategies
Mittr automatically retries failed deliveries with configurable backoff, circuit breakers, and rate limiting.
Retry policy
Section titled “Retry policy”Each endpoint has its own retry configuration:
| Setting | Default | Description |
|---|---|---|
maxRetries | 5 | Maximum delivery attempts |
retryBackoffMs | 1000 | Initial backoff (1 second) |
retryBackoffMax | 86400000 | Maximum backoff (24 hours) |
retryBackoffMult | 2.0 | Exponential multiplier |
timeoutMs | 30000 | HTTP request timeout (30 seconds) |
Default retry schedule
Section titled “Default retry schedule”Mittr’s default schedule is a fixed sequence covering a full day, front-loaded so transient failures recover quickly:
Attempt 1: 1 secondAttempt 2: 5 secondsAttempt 3: 30 secondsAttempt 4: 2 minutesAttempt 5: 10 minutesAttempt 6: 30 minutesAttempt 7: 1 hourAttempt 8: 2 hoursAttempt 9: 6 hoursAttempt 10: 24 hours → dead letter if all failEach delay includes ~10% random jitter to avoid thundering-herd on a destination that recovers all at once.
Per-event override: set maxAttempts when creating an event to cap
attempts at a smaller number for less-critical events.
Custom backoff per endpoint
Section titled “Custom backoff per endpoint”The defaults above kick in when an endpoint doesn’t set its own
backoff. If you set retryBackoffMs, retryBackoffMult, and
retryBackoffMax on an endpoint, the engine switches to a
classical exponential curve for that endpoint only:
delay = min(retryBackoffMs * (retryBackoffMult ^ attempt), retryBackoffMax)Mixing both is supported per-endpoint — use defaults for most, and override only where you have a reason (e.g. a fast-recovering internal service might want a short, tight curve).
Circuit breaker
Section titled “Circuit breaker”Per-endpoint circuit breakers prevent hammering a failing destination:
| Setting | Default | Description |
|---|---|---|
circuitThreshold | 5 | Consecutive failures to open circuit |
circuitResetMs | 60000 | Recovery check interval (60 seconds) |
States
Section titled “States”- Closed — normal delivery. Failures increment the counter.
- Open — after
circuitThresholdconsecutive failures, the circuit opens. Deliveries are queued but not attempted. This protects both Mittr and the destination. - Half-open — after
circuitResetMs, one test delivery is attempted. If it succeeds, the circuit closes. If it fails, the circuit re-opens for another reset interval.
Closed → (5 failures) → Open → (5 min) → Half-open → success → Closed → failure → OpenEvent lifecycle
Section titled “Event lifecycle”queued → delivering → delivered (success) → failed (retryable, scheduled for next attempt) → dead (max retries exhausted, permanent failure)Status descriptions
Section titled “Status descriptions”| Status | Meaning |
|---|---|
queued | Waiting to be picked up by a worker |
delivering | Currently being sent |
delivered | Successfully delivered (HTTP 2xx response) |
failed | Delivery failed, retry scheduled |
dead | All retries exhausted, permanently failed |
Dead letter queue
Section titled “Dead letter queue”After all retries are exhausted, events move to dead status. Dead events can be:
- Viewed in the dashboard with full attempt history
- Edited — change destination or payload, then resend:
PATCH /api/v1/events/{id} - Replayed as-is:
POST /api/v1/events/{id}/replay - Batch retried by status:
POST /api/v1/events/batch/retry
Replay resets the attempt counter and re-queues the event for delivery.
Rate limiting
Section titled “Rate limiting”Per-endpoint rate limiting prevents overwhelming destinations:
{ "rateLimitPerSec": 100 }- Set to
0for unlimited (default) - Rate-limited deliveries are re-queued with backoff
- Rate limit is capped by your plan’s maximum (e.g., Free plan: 10 req/s)
Usage counting
Section titled “Usage counting”Only successful deliveries count toward your monthly message quota. Failed attempts, dead events, and retries do not consume quota. An event that takes 3 attempts to deliver counts as 1 message.