Skip to main content
Olimpijski Kviz — Milano-Cortina 2026 — hero image
Web App Live 2026

Olimpijski Kviz — Milano-Cortina 2026

Real-time quiz platform for 25,000 concurrent viewers during live Olympic broadcasts

Tech Stack

Fastify TypeScript HTMX Tailwind Prisma Redis BullMQ PM2 Prometheus

Overview

A real-time interactive quiz platform built for the Milano-Cortina 2026 Winter Olympics. Every evening during the Games (Feb 6–21), TV Slovenia 2 broadcast a QR code and up to 25,000 viewers joined a live quiz on their phones — answering 16 timed questions about Olympic history, Slovenian athletes, and winter sports trivia, competing for a trip to the LA 2028 Summer Olympics.

16 daily quizzes. 15 seconds per question. Time-based scoring. Live leaderboards. All synchronized without WebSockets.

Olimpijski Kviz — Milano-Cortina 2026 screenshot

The Challenge

  • Keep 25,000 concurrent mobile users in sync during a live TV quiz with sub-second accuracy
  • Handle answer submissions idempotently under unreliable mobile connections (double-taps, retries, network drops)
  • Deliver a smooth, real-time experience using server-side rendering only — no WebSockets, no client-side JS framework
  • Integrate sponsor video ads mid-quiz without breaking the flow
  • Go from zero to production in ~4 weeks
Olimpijski Kviz — Milano-Cortina 2026 screenshot

The Solution

A poll-based state synchronization architecture: HTMX morph-swaps poll the server every 1–2 seconds, and a Redis-cached quiz state machine drives phase transitions automatically via BullMQ workers.

State machine with 6 phases manages each quiz: LOBBY → QUESTION → SPONSOR_EXPOSITION → WAITING → STANDINGS → COMPLETED

Caching layer with 95%+ Redis hit rate eliminates database pressure — leaderboard queries reduced from ~25,000 to 1 per question round (25,000× improvement). TTL jitter prevents cache stampedes.

Idempotent submissions via Prisma transactions prevent double-counting. Distributed Redis locks prevent race conditions during phase transitions.

Olimpijski Kviz — Milano-Cortina 2026 screenshot

Key metrics

Metric Value
Concurrent users 25,000
Throughput 2,959 req/sec sustained
Median latency 108 ms
Requests under load test 1,066,605 (zero failures)
HTTP success rate 100%
Cache hit rate 95%+
N+1 query elimination 25,000× reduction
Quizzes delivered 16 (daily, Feb 6–21)
Questions per quiz 16 (4 choices, 15 sec timer)
Olimpijski Kviz — Milano-Cortina 2026 screenshot

Codebase

TypeScript files 141 (43,044 LOC)
JavaScript (k6 load tests) 13 (2,132 LOC)
Total lines 58,226
Test files 34 (19,000+ LOC)
Prisma models 13
Database indexes 30+ strategic
k6 load test scenarios 13
Olimpijski Kviz — Milano-Cortina 2026 screenshot

Architecture

Architecture

  • Fastify v5 + TypeScript — SSR with fluent-html + HTMX + Tailwind
  • PostgreSQL + Prisma — 13 models, connection pooling (6 per process)
  • Redis — quiz state cache, leaderboard cache, distributed locks, pub/sub
  • BullMQ — phase advancement worker (1s tick), leaderboard aggregation, email delivery
  • PM2 — multi-process clustering across 3–6 × 8vCPU servers
  • Prometheus + Grafana + Loki — real-time monitoring and alerting
  • Cloudflare — DDoS protection, CDN, R2 file storage
Olimpijski Kviz — Milano-Cortina 2026 screenshot

Quiz flow

Quiz Flow

  1. TV broadcasts QR code → viewer scans → lands in Lobby
  2. Quiz starts → Question phase (15 sec timer, time-based scoring 50–100 pts)
  3. Optional Sponsor Exposition (full-screen video ad)
  4. Waiting phase (answers locked, suspense builds)
  5. Standings revealed (live leaderboard, 10 sec)
  6. Repeat 16× → Completed → final rankings

Aggregate leaderboard: "Best 10 of 16" scoring — must complete 10+ quizzes to appear in final standings.

Screenshots

Question Screen Standings Screen
Question Standings

Prizes

  • Grand prize: Trip for 2 to LA 2028 Summer Olympics (flights, hotel, tickets)
  • Runner-up: Peak brand Milano-Cortina 2026 Olympic winter jackets
  • Daily draws: VIP Planica ski jumping tickets, Ford Explorer test drives, Peak hoodies

Sponsor integration

  • Mid-quiz video ads: Full-screen sponsor exposition between question rounds
  • Result page overlays: Video ads with frequency capping (sessionStorage-based cooldown)
  • Random fallback: If no quiz-specific sponsor, random sponsor video plays
  • Sponsors reach thousands of engaged, non-skippable viewers at peak attention moments

Infrastructure

Component Spec
App servers 3–6 × 8vCPU (Digital Ocean)
Database PostgreSQL Premium 4vCPU / 16GB
Cache Redis Premium 4GB
Load balancer DO LB + Cloudflare Pro
Monthly cost €713–€1,351 (~€0.06/user)
Deployment GitLab CI/CD, zero-downtime PM2 reload

Performance

Performance

Load tested with k6 on local MacBook Pro M1 (4,000 VUs):

  • 1,066,605 total requests — zero failures
  • 2,959 req/sec sustained throughput
  • 108 ms median response time
  • 98.4% of requests under 1 second
  • 18% latency improvement between test iterations (Jan 12 → Jan 16)