Message lifecycle
Typical state flow:queued: accepted and waiting for dispatch.sent: handed off to provider.delivered: delivered to recipient device/provider state.read: read receipt observed.failed: dispatch failed or provider rejected.
Retry boundaries
- Retry on
429and5xxonly. - Do not retry validation failures (
400,422) before fixing payload. - Use bounded exponential backoff with jitter.
Client idempotency pattern
- Generate an operation key in your app per send intent.
- Save
operation_key -> message_idmapping. - If the same operation is retried, return existing
message_idfrom your store.
Webhook deduplication pattern
Use event IDs to avoid duplicate processing:Reconciliation flow
Server-side webhook processing is designed for idempotent ingestion. Your consumer should still deduplicate events in your own storage.