Grokking the System Design Interview, Volume II
Vote

0% completed

​

Step 2: Requirements

Functional Requirements

Non-Functional Requirements

"Send notifications" covers a one-time passcode that must arrive in seconds and a weekly digest that nobody minds receiving an hour late. Before designing anything, we agree on which jobs the service takes on and how fast, reliable, and isolated it must be.

Functional Requirements

Functional requirements
Functional requirements
  • Multi-channel delivery. Send notifications by email, SMS, mobile push, and in-app. One event can go out on one channel or on several.
  • Real-time and batched notifications. A chat message or a security alert should reach the user within about 1 to 2 seconds. Bulk sends, like a daily digest or a campaign to millions of users, need their own batch path, driven by a schedule or a trigger.
  • Message scheduling. A tenant can ask for a notification at a future time, for example, a meeting reminder 10 minutes before the meeting. The request is stored, and a scheduler sends it when the time comes.
  • Retry on failure. A send can fail for a short-lived reason, such as provider downtime or a network error. The system then retries with exponential backoff, waiting a little longer after each failed attempt. The result is at-least-once delivery: a temporary problem never loses a message, but a message may occasionally arrive twice, which later steps work to prevent.
  • User preferences and opt-out. A user can turn off a notification type or a whole channel, and the system skips it. A user can also choose a channel per type, like SMS for critical alerts and email for newsletters.
  • Multi-tenant support. A tenant can send only to its own users and see only its own data.
  • Content and templates. A tenant defines a template for each notification type, such as "Hello {name}, your order {order_id} shipped.", and the service fills in the data for each event.
  • No channel prioritization. All channels are treated equally. When an event goes out on several channels, each is delivered independently, and none waits for another.
  • In-app notification management. Notifications also appear inside the application, like the bell icon in a social app. The system stores them so a user can fetch the list later, because people miss or dismiss a push. An active session can also receive new items immediately over a WebSocket.
  • API for producers. Applications call an API naming the recipients, the content (usually a template ID plus data), and the channels, for one recipient or a whole list of users.

Two items shape everything that follows. Preferences mean the service cannot simply send what a tenant asks for, and the lack of channel priority means the design must keep channels separate rather than rank them.

Non-Functional Requirements

Non-functional requirements
Non-functional requirements

Scalability. One social network tenant alone could produce hundreds of millions of notifications a day, so the design must scale horizontally, by adding machines, with no single bottleneck.

High throughput. At peak, during a viral post or a major sale, the system may take in tens of thousands of events per second.

Low latency. For push and in-app, the delay from event to device should be about a second, and never more than two. Email and SMS can take up to about a minute. A push arrives on a screen somebody is looking at right now, so a delay is visible, while an email is read later and nobody can tell when it was sent.

High availability. Aim for 99.99 percent uptime. Password resets and security alerts cannot wait for a repair, so the system runs redundant parts across availability zones and keeps working when one part fails.

Durability. Once the system accepts an event, it is stored or queued, and a server crash cannot lose it.

Ordering. Inside one user's feed, notifications appear in the order they happened, so "Order Placed" never shows after "Order Shipped". The order may take a moment to settle, but it must end up right. Global ordering is not required. A per-user promise is far cheaper, because only each user's messages must pass through one ordered stream.

Multi-tenant isolation and security. This covers two promises. For load, one tenant's huge campaign or failure must not delay anyone else's notifications, which may need per-tenant rate limits or separate partitions. For privacy, data is partitioned or tagged by tenant, tenant A can never read tenant B's data, and every tenant authenticates when it calls the API.

Extensibility. Adding a channel such as WhatsApp, or a feature such as digests, should not require a redesign.

Every choice in the steps that follow is checked against this list.

Reading Progress

0%


Vote for new content

On This Page

Functional Requirements

Non-Functional Requirements