Prompt
I'm building a notification system with retries and delivery logs
Latest observation
Oct 14, 2026
OpenAI APIWeb search: off
Sounds good — a notification system with retries and delivery logs usually benefits from a clear separation between:
-
Notification intent
What should be sent, to whom, and by which channel. -
Delivery attempts
Each try to deliver the notification, including retries. -
Delivery log / audit trail
A durable record of every state change and external response.
A solid starting design:
Core entities
notifications
Represents the message to be sent.
idrecipient_idchannel(email,sms,push, etc.)template_idpayloadstatus(pending,processing,sent,failed,cancelled)created_atupdated_at
notification_attempts
One row per delivery try.
idnotification_idattempt നമ്പర్/attempt_numberproviderstatus(queued,sending,success,retryable_failure,permanent_failure)error_codeerror_messagerequest_payloadresponse_payloadstarted_atfinished_at
notification_logs
Append-only audit log.
idnotification_idattempt_idnullableevent_type(created,queued,attempt_started,attempt_succeeded,attempt_failed,retry_scheduled,dead_lettered)detailsJSONcreated_at
Retry strategy
Use a retry policy based on failure type:
- Retryable: network timeouts, provider 5xx, rate limits, temporary SMTP failures
- Non-retryable: invalid recipient, malformed payload, unsubscribed user, hard bounce
Recommended:
- exponential backoff
- jitter
- max attempts
- dead-letter after max attempts
Example:
- attempt 1 immediately
- attempt 2 after 30s
- attempt 3 after 2m
- attempt 4 after 10m
- then fail permanently
Status flow
Typical lifecycle:
pending -> queued -> processing -> sent
or
pending -> queued -> processing -> retry_scheduled -> processing -> failed
Important concerns
- Idempotency: prevent duplicate sends if workers retry or crash.
- Concurrency control: only one worker should process a notification at a time.
- Deduplication: if the same business event triggers multiple notifications, decide whether duplicates are allowed.
- Provider abstraction: keep channel-specific delivery logic behind adapters.
- Observability: store correlation IDs, provider message IDs, latency, and error details.
- Compliance: respect unsubscribe/opt-out, quiet hours, and locale/timezone preferences.
Suggested processing pipeline
- Create notification record
- Enqueue job
- Worker picks up job
- Create attempt record
- Call provider
- Record success/failure
- If retryable failure, schedule next attempt
- Append log event at each step
If you want, I can help you with any of these next:
- a database schema
- an event/state machine design
- a retry algorithm
- a code example in your stack
- an API design for creating and querying notifications