How a hockey analytics data stack works
The end-to-end path from raw game data to an answer you can act on — drawn as one diagram.
Sources
- NHL / SHL APIs
- Play-by-play
- Scrapers
- Your tracking data
Ingestion
- Scheduled jobs
- Raw JSON/CSV
- Landing zone
Storage
- DuckDB / MotherDuck
- Bronze → silver
- Versioned tables
Transforms
- Clean & join
- xG / Corsi models
- Gold marts
Serving
- Notebooks
- Dashboards
- AI / Claude
The 30-second version
- A stack is just five stages: sources → ingestion → storage → transforms → serving.
- You do not need enterprise tools — a scraper, DuckDB/MotherDuck and a notebook go far.
- Own the pipeline once and every future question gets cheaper to answer.
Sources: where the numbers come from
Everything starts with raw data — league APIs, play-by-play feeds, public scrapers, or your own tracked events. The goal at this stage is coverage and reliability, not beauty: capture the raw records exactly as they arrive so you can always reprocess them later.
Ingestion: get it in on a schedule
Ingestion is the boring glue that pays off forever: small scheduled jobs that pull each source into a raw "landing" area. Keep the raw copy immutable. If a transform is wrong next month, you re-run from raw instead of re-scraping the season.
Storage: one place you own
This is the heart of the stack. A single analytical store — DuckDB locally or MotherDuck in the cloud — lets you layer data from raw (bronze) to cleaned (silver) to analysis-ready (gold). You own this layer, so you can switch every tool around it without losing your data.
Transforms: turn events into insight
Transforms clean, join and model the data: shot events become expected-goals values, shifts become Corsi and zone-entry rates, rosters become comparable player profiles. Each model is just SQL or Python that reads gold tables and writes new ones.
Serving: where you (and your AI) ask questions
Finally you consume the gold marts — in a notebook, a dashboard, or by pointing an LLM like Claude at them. Because the hard work is already modeled, the question layer stays fast and cheap, and anyone (or any agent) can ask in plain language.
Build it yourself
- 1Pick one source (start with a public NHL play-by-play scraper).
- 2Load raw files into DuckDB with a single read_json/read_csv query.
- 3Write one silver view that cleans and types the raw events.
- 4Write one gold table (e.g. shots with an xG estimate).
- 5Query it from a notebook — then point Claude at the same tables.
Key terms
Newsletter
Weekly hockey analytics
Data-driven takes on performance, scouting, and team strategy. No fluff — just the numbers that matter.
No spam. Unsubscribe anytime.