fivenines
11/38
Lesson 1.9 99.9%

Notifications, chat, and masked calls

🎯 Objectives
  • Design one Comms service that fans trip events out to push, SMS, WebSocket, chat, and voice.
  • Apply channel fallback and per-event delivery policies.
🔗 Connect

Trip transitions (1.7) and offers (1.6) are the event sources; the realtime gateway (1.1) is one delivery channel among several. Device tokens come from Identity (1.2).

Every producer in the system says what happened ("driver assigned to trip 123"); only the Comms service decides who hears about it, on which channel, in what language, with what fallback. Centralizing this prevents the classic sprawl where every service embeds its own push logic and no one can answer "why did the rider get 3 SMS?" Events carry a policy class: an offer is urgent (WebSocket + push simultaneously, expire after 12 s — a late offer is worse than none); driver arriving falls back from push to SMS after 10 s unacknowledged; a receipt is email, whenever.

Rider–driver chat rides the realtime gateway with offline fallback to push, scoped to the active trip and closed at completion. Calls are placed through a telephony vendor that bridges two legs via a temporary proxy number — neither party ever sees the other's real number, and the mapping dies with the trip. Privacy by construction beats privacy by policy.

flowchart TB
  TRIP["Trip service events"] --> C["Comms service"]
  MATCH["Matching offers"] --> C
  PAY["Payment receipts"] --> C
  C --> POL["Policy engine — audience, channel, urgency, locale, opt-outs"]
  POL --> WSC["Realtime gateway — in-app, instant"]
  POL --> PUSHC["Push — APNs / FCM"]
  POL --> SMSC["SMS vendor — fallback + no-smartphone markets"]
  POL --> EMAILC["Email — receipts, statements"]
  POL --> VOICE["Telephony vendor — masked calls via proxy number"]
  PUSHC -- "unacked 10 s, urgent only" --> SMSC
One event in, policy-routed channels out. The dashed escalation edge is the fallback chain for urgent events.
⚠️ Pitfall

Notifications must be idempotent per (event, recipient, channel) — trip events get retried (2.4 makes this systematic), and duplicate "driver arriving!" pushes read as spam. Store a delivery record keyed on that triple and drop repeats.

Next step

See what actually stuck.

Take the practice scenarios now.