F1 Telemetry Pit Wall
Overview
F1 Telemetry Pit Wall turns the live UDP stream from EA SPORTS F1 25 into a readable race story for two human drivers. During a session it shows the running order, the live interval between the two players, track position, weather and selected-car telemetry. Afterwards it keeps an archive of sessions that can be replayed, compared head to head and grouped into championships.
The problem
The game sends binary packets many times a second, and raw telemetry doesn't tell two racers who is gaining, who is losing or why. The app has to read that stream without falling behind, keep the live view current in the browser, and keep enough history to replay a race after it ends. Packet layouts also differ between the 2025 and 2026 formats, so the same pipeline has to handle both.
Approach
I run ingestion, the web app and the WebSocket server in one custom Node process, and separate the live path from the storage path. Live data goes through Redis pub/sub to Socket.IO clients, while a smaller sample goes to TimescaleDB. High-frequency packet types are throttled on each path so that neither Redis nor the database has to take the full stream. The interface is built around the two players rather than the whole field.
Architecture
UDP ingest and format detection
A custom Node server binds a UDP socket on port 20777. It reads each datagram's 29-byte header, resolves the 2025 or 2026 layout from the packet format, game year, packet size and session context, and drops packets whose size doesn't match. Type-specific parsers then read each field at its byte offset.
Throttled fan-out
Motion, lap and telemetry packets publish to Redis on every 2nd packet and write to the database on every 5th. At a 20 Hz send rate that works out to 10 Hz for the live view and 4 Hz for storage.
Redis to Socket.IO relay
A subscriber listens on the f1:* Redis channels, strips the prefix and emits each message to connected Socket.IO clients. In the browser, a React hook writes those events into a Zustand store that the dashboard reads from.
Time-series and relational storage
Motion, telemetry, lap and car-damage samples go into TimescaleDB hypertables, with a compression policy on chunks older than one day. Telemetry and damage samples are kept only for human-driven cars. Sessions, participants, events, classifications, driver profiles and seasons live in relational tables managed by Prisma.
Replay and archive
A cursor-paged replay API serves stored motion and lap data to a map-first replay page with play, pause, scrub, frame stepping and 0.5x to 4x speed. Session results link to driver profiles, head-to-head records and season standings.
Outcomes
- The full stack of web app, TimescaleDB and Redis starts with one docker compose command.
Takeaways
Parses both the 2025 and 2026 telemetry formats, including the 24-car 2026 grid.
Node test suite covers packet sizes, format detection, car-slot counts and format-specific fields for both layouts.
Nine UI routes cover the live view, session archive, replay, driver profiles, head-to-head, seasons and standings.