E5: Waiting Queue System¶
Overview¶
Bounded Context / Service: Queue Service, Mobile App
Goal: Manage high-demand match ticket sales with fair queuing for 100k+ concurrent users.
Priority: High
Primary User Roles¶
- Fan
Scope¶
In-Scope¶
- Queue join and position assignment
- Real-time position updates (client countdown + server sync)
- Progressive push notifications (position change, near position, your turn)
- 20-minute purchase window enforcement
- Connection resilience (30-minute position persistence)
- Multi-device synchronization (same user = same position)
- Continue shopping while in queue
- Queue closure when sold out
Out-of-Scope¶
- Priority queue for VIPs (use quota instead)
- Queue bypass mechanisms
Features¶
| ID | Feature | Size | Description |
|---|---|---|---|
| E5-F1 | Queue Join and Position Assignment | M | Join queue and get position |
| E5-F2 | Real-Time Position Updates | M | WebSocket/Firebase updates |
| E5-F3 | Queue Progressive Notifications | S | Push at key milestones |
| E5-F4 | Purchase Window Enforcement | S | 20-minute window at front |
| E5-F5 | Queue Connection Resilience | S | 30-minute position persistence |
Dependencies¶
- Redis Cluster for queue data structures
- Firebase Cloud Messaging for push notifications
- WebSocket or Firebase for real-time updates
Technical Architecture¶
Queue Service Extraction
The Queue System is extracted as a standalone auto-scaling microservice separate from the main Symfony monolith. It activates automatically based on traffic demand (e.g., traffic spikes during high-demand sales) — there is no per-match toggle. Implementation details TBD.
Why Extract as Separate Service¶
| Requirement | Challenge in PHP/Symfony | Solution |
|---|---|---|
| 100k+ concurrent connections | PHP not optimized for long-lived WebSocket connections | Node.js or Go runtime |
| Real-time position updates | Blocking I/O impacts other modules | Dedicated service with event loop |
| Independent scaling | Queue traffic 10x higher than checkout | Horizontal pod scaling |
| Blast-radius isolation | Queue surges risk degrading checkout | Separate deployment |
Queue Service Responsibilities¶
- Queue join and FIFO position assignment (Redis sorted set)
- Real-time position updates via WebSocket/SSE
- 20-minute purchase window enforcement
- 30-minute position persistence on disconnect
- Sold-out detection and queue closure
Communication with Monolith¶
Mobile App ──WebSocket──► Queue Service ──Redis Pub/Sub──► Monolith (E4)
│
▼
Redis Cluster
(sorted sets, pub/sub)
| Direction | Protocol | Events |
|---|---|---|
| App → Queue Service | WebSocket | Join, heartbeat, disconnect |
| Queue Service → App | WebSocket | Position updates, turn granted |
| Queue Service → Monolith | Redis Pub/Sub | queue.turn_granted, queue.expired |
| Monolith → Queue Service | REST | /queue/{match_id}/sold-out |
See Microservices Strategy for detailed API contracts.
Risks & Open Questions¶
OQ-E5-1: Queue Throughput
What is the expected queue throughput rate (users processed per minute)?
OQ-E5-2: Bot Detection
What bot detection and prevention mechanisms are required?
Risk: Redis Sizing
Redis cluster sizing for 100k+ concurrent users requires careful planning and load testing.
Related Documentation¶
Last Updated: January 2026