Case Study · Top-Tier F1 Team
Correlating Driver Comms, Telemetry, and Simulator Output at a Top-Tier F1 Team
- Industry
- Motorsport — Formula 1
- Workload
- Pre-season tyre development, live trackside operations, factory simulator correlation
- Data sources
- ECU telemetry · driver radio · pit wall systems · FIA timing feed · factory simulator · component tracking · engineering debrief notes · technical documents
- Stack before / after
- Seven vendor tools, ad-hoc CSV exports, a data scientist writing pandas scripts between sessions → Infino
The Problem
A Formula 1 team runs one of the most instrumentation-dense workloads in industry. During a single pre-season test — seven days on track, two drivers, two sessions per day — an F1 team generates:
- Per-lap telemetry: lap time, sector splits, max speed, tyre temperatures at all four corners, G-forces, throttle and brake traces, engine RPM, fuel load
- Zone-level telemetry: instantaneous readings at every corner entry, apex, exit, braking zone, and straight — across ten circuit zones per lap
- Sensor time-series: fifteen metrics streaming at high frequency through the full session, in Prometheus exposition format from the ECU
- Driver radio transcripts: unstructured text — "tyres are destroyed, no grip left" — with timestamp, stint, lap number, and topic classification
- Pit wall data: every stop's duration, delta vs target, crew error type, compound change, fuel load
- FIA timing feed: every lap from every car on track, for all twenty cars in the paddock
- Component lifecycle: ICE, MGU-H, MGU-K, turbo, energy store, gearbox — km used vs FIA season limits, penalty-risk flags
- Factory simulator output: setup variants, predicted lap times, predicted sector deltas, driver-in-loop sessions
- Engineering debrief notes: free-text post-session commentary, 100–200 words each, written by the lead race engineer
- Technical documents: tyre operations manual, car setup guide, safety limits, compound operating windows
The questions the team needs to answer cross most of these sources simultaneously. When did the driver's grip complaints correlate with tyre temperatures exceeding the compound's upper operating window? Did the new front wing deliver its simulator-predicted gain on track, and under which temperature conditions? How does our pace compare to a specific competitor on rainy vs dry days, by sector? Based on the tyre operations manual and the actual data we've seen this week, what is the optimal warm-up strategy for hard compounds in cold ambient?
These are not separate queries against separate systems. They are single questions that happen to require data from four or five independent sources, joined by time, driver, stint, lap, and circuit zone.
What Breaks Down
The default architecture for this kind of workload is one tool per data type. A telemetry store from the ECU vendor. A time-series database for sensor traces. A vector store for semantic search over radio transcripts and engineer notes. A document store for the manual. A data warehouse for post-session analysis. A spreadsheet for the simulator. A sixth thing for FIA timing. A seventh for component tracking.
The race engineer asking the question doesn't get to answer it. A data scientist pulls CSVs from each system, lines them up in a notebook, writes the join logic, and delivers a chart — after the session ended. By the time the answer arrives, the next session is already underway.
The three hard parts:
Joining by time, not by ID. A driver radio message at 09:22:00 needs to be joined to the telemetry lap that was active at that moment, the zone-level reading for the corner the car was in, and the engineer note written in that afternoon's debrief. None of these share a foreign key. The join is comm.ts BETWEEN lap.ts_start AND lap.ts_end and comm.stint_id = telemetry.stint_id, across data that arrived from completely independent source systems.
Semantic search scoped by structured context. "Find engineer notes mentioning floor damage on Day 3 in rainy conditions." Vector search alone retrieves notes about floor damage from any day. Structured filters alone don't know that "floor damage" is semantically close to "carbon scuff" or "scrape on the underfloor." The useful query does both — and evaluates the structured predicate during the vector graph traversal, not after.
Cross-language queries over one engine. Sensor traces live as time-series and are naturally queried with PromQL: rate(f1_tire_temp_fl_c[5m]) > 0.8. Lap results live as tabular data and are naturally queried with SQL. Driver comms live as text and need semantic search. The question "when did the front-left tyre temperature rate of change correlate with a grip complaint on the radio" requires all three, and the team should not be building three pipelines to answer it.
The Architecture
Trackside / factory data sources
ECU telemetry → per-lap + zone-level + sensor metrics (PromQL)
Pit wall systems → pit stops, strategy calls
FIA timing feed → competitor lap data for all 20 cars
Driver comms → timestamped radio transcripts
Component tracker → FIA compliance, km used, penalty risk
Factory simulator → setup variants, predicted deltas
Engineering debrief → post-session notes, lead engineer
Document management → tyre manual, setup guide, safety limits
All streams feed a single backend
Structured datasets tabular joins, aggregations, time-range queries
Vector-indexed datasets driver comms, engineer notes, technical docs
Time-series datasets sensor metrics, PromQL-native
Governance layer
RBAC: race_engineer / strategy_engineer / driver_performance / factory
Field-level security: competitor-intelligence fields scoped to strategy role
Audit log: every query logged, replayable after the sessionOne backend stores structured records, vectors, and time-series together and queries them in a single request. SQL, QueryDSL, and PromQL all target the same engine, and queries can mix them — semantic search inside a SQL WHERE clause, PromQL range aggregations joined to structured stint metadata, full-text search over engineer notes scoped by day and session.
The Query That Used to Be Impossible
"When did the driver's grip complaints correlate with the front-left tyre temperature exceeding 100°C?"
Before: pull driver comms CSV from vendor system A. Filter to the grip topic. Pull telemetry from vendor system B. Filter to front-left tyre temp over 100°C. Align by timestamp in pandas. Hope the clocks match. Deliver the chart after the session.
After: the agent's first pass is Query DSL against driver_comms alone — a structured filter on topic plus a semantic match on the message body, no SQL parser involved:
{
"index": "driver_comms",
"query": {
"bool": {
"filter": [
{ "terms": { "topic": ["grip", "temperature"] } },
{ "range": { "@timestamp": { "gte": "now-90m" } } }
],
"must": [
{
"semantic": {
"field": "message",
"query": "no grip tyres destroyed",
"k": 20
}
}
]
}
},
"fields": ["stint_id", "lap_number", "driver", "message", "@timestamp"],
"sort": [{ "@timestamp": "asc" }]
}That answers "what is the driver complaining about?" in one request, against one index. The race engineer's actual question also wants the corresponding lap telemetry — that's a second dataset, joined per-lap, which is what SQL is for:
SELECT
c.stint_id,
c.lap_number,
c.message,
c.approx_tire_temp_c AS tire_temp_at_radio,
t.tire_temp_fl_c,
t.lap_time_ms,
t.tire_compound,
t.tire_age_laps
FROM driver_comms c
JOIN lap_telemetry t
ON c.stint_id = t.stint_id
AND c.lap_number = t.lap_in_stint
AND c.driver = t.driver
WHERE c.topic IN ('grip', 'temperature')
AND t.tire_temp_fl_c > 100
AND c.message IN (
SEMANTIC_SEARCH('no grip tyres destroyed', 'message', 20)
)
ORDER BY c.@timestamp;The SEMANTIC_SEARCH clause in the middle of the SQL is doing the work that used to be a separate vector store. The result set pairs every grip-related radio call with the actual lap telemetry around it. A race engineer can ask this in natural language during the session and have the answer before the next lap completes.
Cross-Language: SQL + PromQL
Sensor metrics arrive in Prometheus exposition format from the ECU and are queryable directly:
rate(f1_tire_temp_fl_c{driver="VER",tire_compound="Soft"}[3m])The engineers can ask "show me the rate of temperature rise on the front-left across every soft-compound stint this week, grouped by ambient temperature" and get a PromQL result. The same backend serves SQL for the per-lap joins and semantic search for the radio transcripts. No separate TSDB, no separate PromQL layer, no data sync job.
The question "did the new front wing deliver its simulator-predicted gain on track?" joins the simulator sessions table (predicted delta ms, real lap time ms) against the actual lap telemetry, filtered by setup variant, tyre compound, and conditions:
SELECT s.setup_variant,
s.predicted_delta_ms,
s.real_lap_time_ms,
s.sim_vs_real_delta_ms,
AVG(t.lap_time_ms) AS actual_avg,
COUNT(*) AS laps_evaluated
FROM simulator_sessions s
JOIN lap_telemetry t
ON t.date = s.real_session_date
AND t.tire_compound = s.compound
AND t.fuel_load_kg BETWEEN s.fuel_load_kg - 5 AND s.fuel_load_kg + 5
WHERE s.correlation_available = true
AND s.setup_variant LIKE 'New_Front_Wing%'
GROUP BY s.setup_variant, s.predicted_delta_ms, s.real_lap_time_ms, s.sim_vs_real_delta_ms;The sim-vs-real correlation is the core output. The value isn't the query — it's that one team can produce it without coordinating across four data platforms.
The Agent Team on the Pit Wall
The engineering group that runs a session isn't one analyst asking questions — it's a team of people, each specialized, each under heavy time pressure. The agent team mirrors that and sits on the same shared substrate:
- Tyre agent — monitors tyre temperatures and pressures per stint, detects when a corner is leaving the compound's operating window, correlates with lap time degradation.
- Comms agent — triages driver radio traffic as it arrives. Classifies topics, flags grip complaints, links each message to the lap and zone the car was in at that moment.
- Strategy agent — tracks the FIA timing feed for every car on track. Builds sector-level comparisons, detects pit-stop windows, surfaces undercut/overcut opportunities. Has access to competitor intelligence the other agents don't.
- Simulator-correlation agent — joins factory simulator predictions to real-world lap telemetry as sessions run, computes sim-vs-real delta for each setup variant, and flags where the model is drifting from reality.
- Component agent — tracks the life of each power-unit and gearbox element against FIA season limits, projects penalty risk, flags components approaching thresholds.
- Debrief agent — during and after the session, pulls together lap telemetry, comms, pit data, and simulator context into the structured summary the lead race engineer signs off on.
These agents are not separate services with separate databases. They share one backend — the tyre agent's observations are visible to the debrief agent; the comms agent's topic classifications are used by the tyre agent for correlation; the strategy agent's competitor analysis is available to the debrief agent for post-session write-up. No CSV exports, no handoff latency, no "the strategy tool doesn't know about the tyre tool." Coordination is just reading shared state.
Governance Declared Once, Not Managed Across Seven Tools
Inside an F1 team there are legitimate access boundaries. The strategy engineer has access to competitor pace data — that's what strategy decisions depend on. A performance engineer working on driver development does not need it. A factory-based engineer working on next year's car has different access again. Managing this across seven vendor tools is a full-time headache and an audit risk; declaring it once on the backend makes it disappear.
sdk.create_role("strategy_engineer", permissions={
"datasets": ["lap_telemetry", "driver_comms", "pit_stops",
"competitor_timing", "simulator_sessions",
"component_lifecycle"]
})
sdk.create_role("performance_engineer", permissions={
"datasets": ["lap_telemetry", "driver_comms", "pit_stops",
"simulator_sessions"],
"field_deny": {
"competitor_timing": ["*"],
"component_lifecycle": ["penalty_risk_notes"]
},
"row_filter": {
"lap_telemetry": "driver IN ($user.assigned_drivers)",
"driver_comms": "driver IN ($user.assigned_drivers)"
}
})Three layers of access, all enforced inside the engine on every query the corresponding agent executes:
- RBAC — competitor timing data is visible to the strategy agent and not to the performance agent. Component penalty notes are visible to the component agent and not to driver-performance agents.
- Field-level security — a performance engineer's agent asking about lap times gets lap times. The same query path that would have revealed competitor sector splits returns a scope-limited error before it reaches the data.
- Row-level (document-level) security — a performance engineer responsible for one driver only sees that driver's telemetry and comms, even when writing a query that would otherwise return both drivers. The filter is applied to the row source, not by application code an engineer could bypass by switching query paths.
These rules apply whether the agent is running SQL, PromQL, semantic search, or translating a natural-language question from a trackside console. The audit log captures every request: which engineer, which agent, which datasets, which fields, which rows were filtered out, and when. A post-session review that used to require manual log collation across seven systems is now a query.
Replayable Sessions
The value isn't in the real-time query — that's the happy path. The value is that every question asked during the session is preserved. On Monday morning, the performance team can replay exactly what the race engineer asked on Sunday, in what order, against what data, and what the answers were. Changing a hypothesis and re-running it is one query. The same question against the same data returns the same result — no "I can't reproduce that number."
This is a property of the storage model, not an instrumentation feature. The data is append-only. The audit log is itself a queryable dataset. Post-session analysis runs against the state of the data at session close, not against whatever the current state is after subsequent updates.
What Changed
Before: seven vendor tools, five data pipelines, one data scientist, and a pandas notebook that produced answers after the session ended. Every new "agent" — a tyre-trend monitor, a sim-correlation job, a competitor-pace script — meant another integration point, another copy of credentials, another gap in the audit story. Cross-source questions that mattered during the session were either not asked or not answered in time.
After: one backend. The tyre, comms, strategy, simulator-correlation, component, and debrief agents share the same datasets, the same identity model, and the same audit log. Governance is declared once and enforced inside the engine on every query every agent runs. Adding a new specialist — say, a weather-correlation agent that joins rainfall to tyre behavior — is a role declaration, not a security project across seven tools.
The team still has a data scientist. They're not writing pandas scripts between sessions anymore.
Questions? Get in touch.
