A production-ready, horizontally-scalable real-time sports scoring platform built with Node.js, TypeScript, and modern cloud-native architecture.
Live Score API is a high-performance backend system designed for real-time sports event tracking. It supports horizontal scaling, real-time WebSocket broadcasts, automated match status transitions, and comprehensive monitoring.
- Real-time Updates: WebSocket-based live scoring with sub-100ms latency
- Horizontal Scaling: Multiple API instances share state via Redis Pub/Sub
- TypeScript: Fully typed codebase with strict mode enabled
- Background Jobs: BullMQ for scheduled match status transitions
- Database: PostgreSQL with Drizzle ORM for type-safe queries
- Monitoring: Docker Stats, Redis Monitor, and Artillery load testing
- Security: Arcjet rate limiting and request validation
- Testing: Vitest unit tests, integration tests, and load testing suite
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLIENT LAYER │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Web App │ │ Mobile App │ │ TV App │ │ PWA │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼────────────────┼────────────────┼────────────────┘
│ │ │ │
└────────────────┴────────────────┴────────────────┘
│
┌──────────┴──────────┐
│ Load Balancer │
│ (Nginx/Cloudflare)│
└──────────┬──────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
┌─────────▼─────────┐ ┌────────▼────────┐ ┌────────▼────────┐
│ API Instance 1 │ │ API Instance 2 │ │ API Instance N │
│ (Port 8000) │ │ (Port 8001) │ │ (Port 800N) │
│ │ │ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐│ │ ┌─────────────┐│
│ │ Express │ │ │ │ Express ││ │ │ Express ││
│ │ WebSocket │ │ │ │ WebSocket ││ │ │ WebSocket ││
│ └──────┬──────┘ │ │ └──────┬──────┘│ │ └──────┬──────┘│
└─────────┼─────────┘ └─────────┼────────┘ └─────────┼────────┘
│ │ │
└─────────────────────┼────────────────────┘
│
┌──────────┴──────────┐
│ REDIS │
│ ┌─────────────┐ │
│ │ Pub/Sub │ │ ◄── Cross-instance
│ └─────────────┘ │ broadcasting
│ ┌─────────────┐ │
│ │ Queue │ │ ◄── BullMQ jobs
│ └─────────────┘ │
│ ┌─────────────┐ │
│ │ Cache │ │ ◄── Response caching
│ └─────────────┘ │
└──────────┬──────────┘
│
┌──────────┴──────────┐
│ POSTGRESQL │
│ │
│ • matches │
│ • commentary │
│ • teams │
│ • leagues │
└─────────────────────┘
| Layer | Technology | Purpose |
|---|---|---|
| Language | TypeScript 5.9 | Type-safe development |
| Runtime | Node.js 20+ | Server runtime |
| Framework | Express 5 | HTTP API |
| WebSocket | ws library | Real-time communication |
| ORM | Drizzle ORM | Database abstraction |
| Database | PostgreSQL 16 | Primary data store |
| Cache/Queue | Redis 7 | Pub/Sub, caching, job queues |
| Jobs | BullMQ | Background job processing |
| Security | Arcjet | Rate limiting, bot detection |
| Validation | Zod | Schema validation |
| Testing | Vitest | Unit and integration tests |
| Load Testing | Artillery | Performance testing |
live-score/
├── src/
│ ├── index.ts # API entry point
│ ├── worker.ts # Background worker entry
│ ├── db/
│ │ ├── schema.ts # Database schema (Drizzle)
│ │ └── db.ts # Database connection
│ ├── jobs/
│ │ ├── queue.ts # BullMQ queue setup
│ │ ├── worker.ts # Job processors
│ │ └── processors/ # Job handlers
│ ├── redis/
│ │ ├── client.ts # Redis connection & pub/sub
│ │ └── keys.ts # Key naming conventions
│ ├── routes/
│ │ ├── matches.ts # Match CRUD API
│ │ └── commentary.ts # Commentary API
│ ├── ws/
│ │ └── server.ts # WebSocket server
│ ├── services/
│ │ └── providers/ # External API adapters
│ ├── config/ # Configuration management
│ ├── validation/ # Zod schemas
│ └── types/ # TypeScript types
├── scripts/
│ ├── seed.ts # Database seeding
│ ├── load-test.yml # Artillery load test config
│ ├── test-websocket.html # WebSocket test client
│ ├── test-websocket-scaling.html # Horizontal scaling test
│ └── *.ps1 # PowerShell dev scripts│
├── test/ # Test suites
├── docker-compose.yml # Infrastructure setup
└── README.md # This file
- Node.js 20+
- Docker Desktop
- Git
# Clone repository
git clone <your-repo-url>
cd live-score
# Install dependencies
npm install
# Start infrastructure (PostgreSQL + Redis)
npm run docker:up
# Push database schema
npx drizzle-kit push
# Seed test data
npm run db:seed
# Build project
npm run buildnpm run devSelect from:
[1] BASIC Setup- 5 windows (API, Worker, Redis, Postgres, Test)[2] FULL Setup- 7 windows (+ Docker Stats, Load Test ready)[3] Windows Terminal Tabs- All services in one window[4] Docker Stats- Container monitoring[5] Load Test- Run Artillery tests[6] Horizontal Scaling- Verify Redis Pub/Sub
# Terminal 1: Start API
npm run dev:ts
# Terminal 2: Start Worker
npm run worker:dev
# Terminal 3: Monitor Redis
npm run redis:monitor# Health check
curl http://localhost:8000/health
# Get matches
curl http://localhost:8000/api/matches
# Get match commentary
curl http://localhost:8000/api/matches/1/commentary
# Open WebSocket test client
start scripts/test-websocket.html| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Health check with service status |
| GET | /api/matches |
List all matches (with pagination) |
| POST | /api/matches |
Create new match |
| GET | /api/matches/:id |
Get match details |
| GET | /api/matches/:id/commentary |
Get match commentary |
| POST | /api/matches/:id/commentary |
Add commentary event |
Connect: ws://localhost:8000/ws
Client → Server:
{"action": "subscribe", "matchId": 1}
{"action": "unsubscribe", "matchId": 1}Server → Client:
{"type": "score:update", "matchId": 1, "data": {"homeScore": 2, "awayScore": 1}}
{"type": "commentary:new", "matchId": 1, "data": {...}}
{"type": "match:status", "matchId": 1, "data": {"status": "live"}}npm testCoverage: 29 tests covering validation, match status logic, and utilities.
# Requires running PostgreSQL
npm run test:integration# Install Artillery (one-time)
npm install -g artillery
# Run load test
npm run test:loadTest configuration: scripts/load-test.yml
- 4 phases: Warm up → Normal → Peak → Cool down
- Tests match browsing, commentary, and health endpoints
- ~5 minute duration
Verify multiple instances share broadcasts via Redis:
npm run test:scalingOr use browser test:
start scripts/test-websocket-scaling.html# Instance 1
$env:PORT=8000
npm run dev:ts
# Instance 2
$env:PORT=8001
npm run dev:ts- Stateless API: Any instance can handle any request
- Redis Pub/Sub: WebSocket broadcasts reach all instances
- Shared Database: Consistent data across all instances
- BullMQ: Distributed job processing
- Connect WebSocket clients to different ports
- Send update via Instance 1
- Verify clients on Instance 2 receive it
matches - Match data and scores
id,homeTeam,awayTeam,homeScore,awayScorestatus: scheduled | live | halftime | finishedstartTime,endTime,elapsedSecondsstats(JSONB): possession, shots, cards, etc.
commentary - Match events
matchId,minute,eventTypeactor,team,messagemetadata(JSONB): assists, substitutions, VAR decisions
See DATABASE_SCHEMA.md for complete documentation.
# Database
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/live_score
# Redis
REDIS_URL=redis://localhost:6379
# Server
PORT=8000
NODE_ENV=development
# Security
ARCJET_KEY=your_key_hereSee .env.example for all options.
npm run docker:statsShows real-time CPU, memory, and network for PostgreSQL and Redis containers.
npm run redis:monitorView all Redis commands in real-time to verify pub/sub broadcasts.
npm run postgres:logsversion: '3.8'
services:
api:
build: .
ports:
- '8000:8000'
environment:
- DATABASE_URL=postgresql://postgres:pass@postgres:5432/live_score
- REDIS_URL=redis://redis:6379
deploy:
replicas: 3
worker:
build: .
command: npm run worker
environment:
- DATABASE_URL=postgresql://postgres:pass@postgres:5432/live_score
- REDIS_URL=redis://redis:6379
postgres:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
- redisdata:/data✅ TypeScript Migration: Complete codebase converted from JavaScript with strict mode ✅ Real-time Architecture: WebSocket + Redis Pub/Sub for horizontal scaling ✅ Background Jobs: BullMQ for match status automation ✅ Comprehensive Testing: Unit tests, integration tests, load tests ✅ DevOps Ready: Docker Compose, monitoring scripts, automated setup ✅ Documentation: 6 detailed documentation files
[Nemanja Stojanovic] - [GitHub] - [LinkedIn/GitHub]
Built with modern cloud-native architecture principles for production-scale deployments.