Delivery, retries, and idempotency
Delivery behavior
Section titled “Delivery behavior”| Behavior | What to expect |
|---|---|
| Success | Any HTTP status below 400. Respond as soon as you have stored the payload. |
| Timeout | 5 seconds. Do your processing after responding, not before. |
| Retries | Up to 10 retries after the first attempt. The delay starts at 30 seconds and doubles each time — 30s, 1m, 2m, 4m, and so on up to roughly 4 hours — about 8½ hours of attempts in total. |
| Giving up | After the last retry the delivery is marked failed and stays in the portal, where you can retry it by hand. |
| Duplicates | Delivery is at-least-once, so the same event can arrive more than once. Deduplicate on the payload’s id. |
| Ordering | Not guaranteed. Order by date_time, not by arrival. |
Deduplicate by event
Section titled “Deduplicate by event”Use the stable payload id to make business processing idempotent. Store it with the result of processing and skip work you have already completed.
Do not use delivery.id for business deduplication. It identifies one generated delivery and changes when Levno rebuilds the payload.
Suggested handling pattern
Section titled “Suggested handling pattern”- Validate the event envelope.
- Start a transaction in your own system.
- Insert the stable event
idinto a table with a unique constraint. - Apply the business change only when the insert succeeds.
- Commit, then return a success status below 400.
This pattern makes duplicate deliveries harmless regardless of retry timing.
Recommendations
Section titled “Recommendations”- Return success quickly and do the real work asynchronously — a slow endpoint turns into retries and duplicates.
- Verify the signature on every request — see verifying webhooks.
- Make your handler idempotent, keyed on the payload
id. - Ignore fields you do not recognise instead of rejecting the payload.
- Keep your endpoint’s TLS certificate valid — an expired certificate looks like a failed delivery.