Appearance
ADR-007: Real-Time Strategy
Status: Accepted Date: 2026-02-07
Context
The platform requires real-time features for collaboration: activity feed updates, notifications when content changes, and eventually live collaborative editing indicators. The team needed to decide when to introduce real-time and which technology to use.
Decision
SignalR from Phase 1, starting with basic activity feed notifications and expanding in later phases.
Rationale
- SignalR is built into .NET - minimal setup cost
- Having it in the architecture from Phase 1 avoids retrofitting later
- Phase 1 scope is limited: push notifications for activity feed events (e.g., "Alex added a new character")
- Phase 3 expands to collaborative features (editing indicators, live comments)
- SignalR handles WebSocket connections with automatic fallback to Server-Sent Events and long polling
Phased Rollout
| Phase | Real-Time Features |
|---|---|
| Phase 1 | Activity feed notifications ("user X did Y") |
| Phase 2 | Relationship map live updates (new character/relationship appears for other viewers) |
| Phase 3 | Comment notifications, @ mention alerts, "someone is editing" indicators |
| Phase 4 | Live changelog updates |
Alternatives Considered
- Skip real-time for Phase 1 - Users refresh to see changes. Simplest path but worse UX and harder to add later
- Server-Sent Events (SSE) - Simpler than WebSockets, one-directional. Sufficient for notifications but doesn't support bidirectional communication needed in Phase 3
- Polling with optimistic UI - No persistent connection. Higher latency, more server load. Not recommended for a collaborative tool
- Third-party (Pusher, Ably) - Managed WebSocket services. Adds external dependency and cost for something .NET handles natively
Consequences
- SignalR hub(s) live in the Infrastructure project
- Need to consider SignalR scaling if deploying multiple server instances (Redis backplane or Azure SignalR Service)
- Permission checks must apply to real-time events (don't push private content notifications to unauthorized users)
- Frontend needs SignalR client library