Skip to main content

SECTION 0 — REALTIME IS A DISTRIBUTED SYSTEM IN DISGUISE

Realtime features fail in predictable ways:

  • reconnect storms

  • fanout overload

  • ordering bugs

  • duplicate delivery

  • memory blowups from slow clients

Senior fullstack means your UI and backend cooperate on correctness and backpressure.


SECTION 1 — REQUIREMENTS

  • Show realtime notifications in web UI.

  • Mark as read.

  • Support offline users.

  • Delivery should be “near realtime,” not necessarily exactly-once.


SECTION 2 — TRANSPORT CHOICE: SSE VS WEBSOCKET

SSE

  • server → client only

  • simpler infra

  • works well behind proxies

WebSocket

  • bidirectional

  • supports richer protocols

  • more operational complexity

Senior default:

  • Use SSE if you only need server → client events.

  • Use WebSocket if you need client → server realtime interactions (chat typing, multiplayer, etc.).


SECTION 3 — EVENT MODEL + CONTRACT

Events should be versioned and typed:

  • notification.created

  • notification.read

Envelope:

  • eventId (monotonic per user if possible)

  • type

  • payload

  • occurredAt

Client contract:

  • client sends last seen eventId on connect

  • server can replay missed events (bounded)


SECTION 4 — ARCHITECTURE

Producer services -> event bus/queue -> notification service
-> fanout to connections
-> store for offline

Data:

  • durable store for notifications

  • ephemeral connection registry (in-memory/redis)


SECTION 5 — BACKPRESSURE (THE SENIOR DIFFERENCE)

Slow clients are normal.

Mitigations:

  • per-connection send buffer limits

  • drop policy for non-critical events

  • disconnect slow consumers (with retry)

  • compress/batch events

Server rule:

Protect the system first; protect perfect delivery second.


SECTION 6 — ORDERING + DEDUPE

  • Provide ordering per user via eventId sequence.

  • Client de-dupes by eventId.

  • Delivery is at-least-once; UI must be idempotent.


SECTION 7 — FRONTEND STATE

States:

  • CONNECTING

  • CONNECTED

  • DEGRADED (retry/backoff)

  • OFFLINE (explicit)

UX rules:

  • show last updated time

  • allow manual refresh

  • never block core navigation on realtime


SECTION 8 — FAILURE MODES

  • reconnect storm during deploy → exponential backoff + jitter

  • fanout overload → partition by userId, scale horizontally

  • missed events → replay endpoint: GET /notifications?sinceEventId=...

  • duplicate events → client de-dupe


SECTION 9 — OBSERVABILITY

  • active connections

  • events delivered/sec

  • buffer drops

  • reconnect rate

  • p95 event delivery latency


SECTION 10 — EXERCISES

  1. Decide SSE vs WebSocket for your use case and justify.

  2. Define your event envelope and versioning strategy.

  3. Design your backpressure policy and what gets dropped.

  4. Write the reconnect algorithm (backoff + jitter) for the UI.


🏁 END — REALTIME NOTIFICATIONS CASE STUDY