Live Scoring Architecture: Handling Million-Viewer Concurrency
Live scoring at million-viewer concurrency is a specific engineering discipline. Here's the architecture that holds up under real load.
Key takeaways
- Event-sourced backend: every match event is an immutable record.
- Fan-out via push (WebSockets or SSE) for active viewers; pull (HTTP) for passive.
- Leaderboards via Redis sorted sets, eventually consistent.
- Edge caching for less time-sensitive views.
- Observability is non-negotiable.
The architecture
Event ingestion
Data feeds (cricket: ball-by-ball; football: play-by-play) ingest into a Kafka topic. Each event is immutable, timestamped, ordered.
Processing
Event consumers compute derived state: scores, rankings, fantasy contest standings. Write to a fast store (Redis, DynamoDB).
Fan-out to viewers
Active viewers (users with app open) connect via WebSocket or SSE. New events push to relevant viewers.
Inactive viewers (background) pull via standard HTTP on app foreground.
Leaderboards
Redis sorted sets handle million-user leaderboards. Sub-millisecond rank queries.
Edge
Static or slow-changing views (player info, match metadata) cached at CDN edge.
Scale patterns
Sharding
Partition users by contest, by region, by user ID. Each shard has bounded work.
Read replicas
Primary handles writes (event ingestion + state updates). Replicas serve reads.
Async everything non-critical
Notifications, secondary updates, analytics, all async.
Pre-warming
Known peak times (IPL final): pre-scale 30 minutes ahead.
What goes wrong
Hot rows
Top-scored player's row gets hammered. Cache it.
Cascading failures
One slow service slows everything. Circuit breakers between services.
WebSocket scale
WebSockets are expensive at million-scale. Use them only for the most engaged users; HTTP polling for the rest.
Data feed gaps
Provider misses an event. Have replay capability.
Observability
Dashboards for:
- Event ingestion lag
- WebSocket connections per shard
- Leaderboard query latency
- Cache hit rates
- Error rates by API
War room during live events.
Common pitfalls
Trying to make everything real-time. Some data can lag 5-10 seconds; users don't notice.
Single point of failure. Multi-region active-active for major events.
Database for hot leaderboards. Use Redis.
No load test at expected peak. Test at 2x peak before live.
What we recommend
Event-sourced foundation. Redis for hot reads. WebSockets only where needed. Multi-region. Load-test obsessively.
FAQs
Edge for live scoring? Some data yes (player metadata); core scoring data not really.
Polling fallback? Always. WebSockets fail.
Mobile-friendly? Critical, most viewers on mobile.
