> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Notification System The Notify API and the Data Model

> Designing an asynchronous Notify API and data model for resilient delivery, queuing, retries, and scaling with external push, SMS, and email providers.

Start the design with a quick back-of-the-envelope estimation to understand scale and failure modes.

* Ask for expected throughput: how many notifications per day? Is traffic steady or bursty?
* Example: 10 million notifications/day ≈ 115 notifications/second on average — modest for most databases and queues.
* Always ask for peak/arrival patterns. A marketing blast to 1 million users at 09:00 AM creates a massive burst that must be handled without dropping messages.

Remember: we do not deliver messages ourselves. Push notifications, SMS, and email are delivered by external providers (APNs, FCM, Twilio, SendGrid), and those systems can be slow or unavailable.

<Callout icon="lightbulb" color="#1CB2FE">
  External providers are out-of-process. Design for retries, timeouts, idempotency, and backpressure — you cannot assume constant availability or latency from third-party services.
</Callout>

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/CjAdnUFCNZoN2k5-/images/System-Design-for-Interview-Prep/Fan-Out-One-Event-Many-Readers/Notification-System-The-Notify-API-and-the-Data-Model/notification-routing-push-sms-email-providers.jpg?fit=max&auto=format&n=CjAdnUFCNZoN2k5-&q=85&s=32b3d87376c472188cce770d47939eb1" alt="A dark-themed infographic showing three notification channels—Push, SMS, and Email—being routed to external providers (APNS, FCM, Twilio, SendGrid) in a dashed &#x22;external systems&#x22; box. A right-hand sidebar lists numbered notes, and small &#x22;interviewer&#x22; and &#x22;you&#x22; icons sit at the bottom." width="1920" height="1080" data-path="images/System-Design-for-Interview-Prep/Fan-Out-One-Event-Many-Readers/Notification-System-The-Notify-API-and-the-Data-Model/notification-routing-push-sms-email-providers.jpg" />
</Frame>

Keep these operational realities in mind: calls to external providers can vary from tens to hundreds (or more) of milliseconds and sometimes fail. Your system must be resilient to variable latency and failures.

API design (high level)

The Notify API should be simple and asynchronous from the caller’s perspective:

* Single POST /notify endpoint.
* Caller provides the target, message, and delivery channels.
* The API accepts the request, persists a notification record, and returns immediately with an identifier (for tracing and status checks).
* Actual delivery is performed asynchronously by worker/dispatcher processes that talk to external providers.

Example request and immediate response:

```http theme={null}
POST /notify HTTP/1.1
Content-Type: application/json

{
  "user_id": "alan",
  "channels": ["push","sms","email"],
  "body": "Payment of $42.00 went through",
  "metadata": { "order_id": "A-4417" }
}
```

```http theme={null}
HTTP/1.1 202 Accepted
Content-Type: application/json

{ "id": 35 }
```

Why return immediately?

* Keeps the caller fast and decoupled.
* Lets you buffer work and apply retries, rate-limiting, and backoff without blocking the originating service.
* The returned notification ID is critical for tracing, dashboards, and user-facing status queries.

Data model (minimal required fields)

Store enough metadata to:

* Route notifications (phone, device token, email).
* Track state and retries.
* Support in-app visibility (seen/unseen).
* Correlate notifications to business objects (orders, refunds, etc.).

Recommended fields:

| Field | Type | Description | Example |
| - | - | - | - |
| `notification_id` | integer / uuid | Unique ID for tracing and status | `35` |
| `user_id` | string | Target user identifier | `alan` |
| `channels` | array | Channels to attempt delivery on | `["push","sms","email"]` |
| `body` | text | Message content | `Payment of $42.00 went through` |
| `status` | enum | Overall state: pending, sending, sent, failed | `pending` |
| `created_at` | timestamp | When notification was created | `2023-09-17T09:41:02Z` |
| `seen` | boolean | For in-app notifications only | `false` |
| `metadata` | json | Product-specific fields (order\_id, etc.) | `{"order_id":"A-4417"}` |

Illustrative example layout:

```text theme={null}
NOTIFICATIONS
notification_id        35
user_id                alan
channels               push,sms,email,in-app
body                   Payment of $42.00 went through
status                 pending
created_at             2023-09-17T09:41:02Z
seen                   false
order_id               A-4417

USERS
name                   Alan Reid
user_id                alan
phone                  +44 7700 900123
email                  alan@example.com
device_token           d4f9...a17c
marketing_sms          OFF
```

Database choice and scaling

* A relational database such as Postgres is a reasonable starting point: each notification is a small row and Postgres handles thousands of writes per second with proper tuning.
* At \~10M notifications/day (≈115 writes/sec average), Postgres can perform well with indexes, partitioning, and batch writes.
* For burst protection, add buffering between the API and the DB (an in-memory queue or durable message queue) or use write batching/partitioned tables.
* For very large scale or long-term archival, consider an append-only log or a time-partitioned store and move cold data to cheaper storage.

Operational recommendations

* Use a durable queue (e.g., Kafka, RabbitMQ, SQS) or DB-backed work table for dispatchers to pick up pending notifications.
* Implement idempotency keys for retries with external providers.
* Use exponential backoff + jitter when retrying failed deliveries.
* Maintain per-provider rate limiting to avoid being throttled by APNs/FCM/Twilio/SendGrid.
* Record provider-specific delivery status and error codes for observability and debugging.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/CjAdnUFCNZoN2k5-/images/System-Design-for-Interview-Prep/Fan-Out-One-Event-Many-Readers/Notification-System-The-Notify-API-and-the-Data-Model/postgres-throughput-notifications-users.jpg?fit=max&auto=format&n=CjAdnUFCNZoN2k5-&q=85&s=7bbc22720f9d91173b69cd4b0b1988fd" alt="A dark-themed diagram showing two glowing panels labeled &#x22;Notifications&#x22; and &#x22;Users&#x22; with example database fields and values. Arrows link the panels to a central Postgres icon with throughput notes (e.g., 10,000,000 a day, ~100 writes a second)." width="1920" height="1080" data-path="images/System-Design-for-Interview-Prep/Fan-Out-One-Event-Many-Readers/Notification-System-The-Notify-API-and-the-Data-Model/postgres-throughput-notifications-users.jpg" />
</Frame>

Links and references

* APNs (Apple Push Notification service): [https://developer.apple.com/documentation/usernotifications/setting\_up\_a\_remote\_notification\_server](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server)
* FCM (Firebase Cloud Messaging): [https://firebase.google.com/docs/cloud-messaging](https://firebase.google.com/docs/cloud-messaging)
* Twilio SMS: [https://www.twilio.com/sms](https://www.twilio.com/sms)
* SendGrid Email: [https://sendgrid.com/](https://sendgrid.com/)
* Postgres: [https://www.postgresql.org/](https://www.postgresql.org/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/system-design-for-interview-prep/module/36e67187-d5c7-44a8-9c92-65e2548b2f80/lesson/eb8ff480-44cf-496a-b767-b259f7a81a7e" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.