Reader’s retry policy
- Timeout per attempt: 10 seconds
- Retry schedule: exponential backoff (1s, then 4s, then 16s)
- Max attempts: 3
- Giving up: after the third failed attempt, Reader marks the delivery as failed in the webhook’s
deliveryStatsand stops trying
- Your endpoint returns non-2xx (5xx error, 4xx auth failure, HTML error page)
- Your endpoint is unreachable (connection refused, DNS fails)
- Your endpoint is slow. Reader waits 10 seconds, times out, retries
The duplicate-delivery trap
The trickiest case is when your endpoint did succeed but Reader thought it didn’t. For example:- Reader POSTs the event
- Your handler processes it, writes to the database, returns 200
- The response packet is dropped on the network path back to Reader
- Reader times out, schedules a retry
- Reader POSTs again: duplicate delivery, but your first attempt really did run
The idempotency key
Every delivery includes a uniqueX-Reader-Delivery header, a UUID that’s stable across retries of the same delivery. Use it as your dedupe key.
Transactional recording
The robust pattern: record the delivery ID in the same transaction as the side effect. That way, either both happen or neither does.Returning 200 quickly
Reader gives you 10 seconds. If your event handler does slow work (embedding text, calling other APIs, running LLMs), push it into a queue and return 200 immediately.Monitoring failed deliveries
The webhook’sdeliveryStats field tracks:
totalAttempts: every attempt Reader has madefailedDeliveries: how many of those exhausted retries without successlastDeliveryAtandlastDeliveryStatus
failedDeliveries is climbing, your endpoint has a problem; investigate before the next batch silently drops.

