Writing

Notes on notification infrastructure

What sits between a send call and a delivered message: multi-tenant branding, real-time delivery, preferences, retries, and the parts nobody scopes up front.

Subscribe via RSS
Tutorial 8 min read

Add a notification inbox to your React app

A complete walkthrough for adding an in-app notification inbox to a React app: the notification type and its template, a token endpoint on your backend, the provider and bell in the frontend, and the two mistakes that only show up on the second page load.

Read the post
Delivery 6 min read

Never mark a failed send permanent

Classifying a send failure as permanent or transient is not a neutral choice. Being wrongly retryable wastes a few attempts. Being wrongly permanent destroys the message. Design for the asymmetry.

Read the post
Product design 7 min read

Browser push is a channel, not a provider

Web push shares a queue, a worker and a payload shape with mobile push, so modelling it as another provider looks free. It is not: a contact's opt-out is keyed by channel, and a channel is the one thing you cannot split after the fact.

Read the post
Build vs. buy 13 min read

The notification system you didn't plan to build

Sending one email is one line of code. The system around it (per-tenant branding, preferences, retries, a real-time inbox that doesn't poll) takes months. When to build it, and when to buy it.

Read the post
Product design 4 min read

Four rules for notification preferences

The type-by-channel grid is the easy part. Four rules for what breaks after it: store overrides not the grid, non-opt-out does not mean always sent, only offer channels a template can deliver on, and never let a config change delete a choice.

Read the post
Real-time 6 min read

Your notification inbox does not need WebSockets

Server-sent events versus WebSockets for an in-app notification inbox: what the feature actually needs, the real drawbacks of SSE including the header auth problem, and why the stream must never be the source of truth.

Read the post