Behind the comparison

From saved results to a useful chart.

The chart is the last step. Cloud Storage, Cloud Run, BigQuery and dbt help turn fixed race results and ERA5 weather into a checked comparison that the read-only page can show.

Follow one real edition Folkestone Half Marathon · 2019

459 accepted results 459 weather matches

The evidence below comes from separate verified executions of this same fixed edition, including an Airflow run. It is not a continuously updated feed.

The data journey

Six steps from source to screen

The path and its safeguards are visible here. Open a step for the implementation detail and its evidence.

  1. Saved race result + ERA5 weather Qualify the inputs Check the race date, start, course evidence and source files. Input hashes

    Why: fixed source bytes and their SHA-256 hashes make a later run traceable to the exact race and weather inputs. A matching hash proves identity, while source qualification checks whether those bytes describe the intended race.

    See the Folkestone input checks
  2. Audit report JSON + result-row NDJSON Validate and export Python checks each result and matches ERA5 weather to the run. Validation gate

    Why: the Cloud Run export job calls the same parsing, validation and weather-matching code used locally. It records candidate outcomes and fails if the source structure or weather is unusable. Folkestone produced 459 accepted results and 459 weather matches.

    See the export check
  3. Explicit BigQuery snapshot table Store and read back the rows Validate the whole export, then verify the typed warehouse rows. No overwrite

    Why: a fixed snapshot has its own destination. An identical rerun checks the existing rows instead of loading them again; a changed snapshot needs a separate destination. The Folkestone cloud export was checked against its protected 459-row table without another load.

    See the warehouse readback
  4. Edition views + course comparison view Build the comparison in dbt Run edition models and tests before the comparison build. Tests first

    Why: dbt owns pace and weather summaries. The Cloud Run dbt job uses the same stage runner as local work; it stops downstream work if an earlier stage fails. Folkestone 2019 and its three-edition comparison passed the native build.

    See the dbt execution
  5. Reconciliation + execution evidence Check the result independently Compare important BigQuery values with saved expectations. Readback

    Why: a passing dbt command alone is not enough. Separate readback checks compare counts and statistics after the models run. Successful and failed executions retain useful evidence; a failed stage blocks later tasks, although views already created in BigQuery can remain.

    See the Airflow checks
  6. Prepared mart → API → chart Show the comparison The public page reads prepared summaries, not raw result rows. Read only

    Why: the Cloud Run API selects approved BigQuery comparison views and returns aggregate fields. It does not parse race files or recalculate the statistics. Weather and pace are shown together as descriptive context, not a measured weather effect.

    See the API contract

Key design decisions

Why the pipeline works this way

The choices follow the workload: saved historical races, repeatable checks and a small public comparison.

01 / Fixed inputs

Know exactly what was processed.

Source hashes identify each saved race and weather file. Validation happens before output, and an identical rerun verifies the existing snapshot. A corrected input gets a distinct snapshot. More elaborate revision and publication controls can wait for a changing feed.

02 / Shared processing

One set of checks in each environment.

The local export command and Cloud Run export job reuse the tested Python parsing, validation and export code. The dbt stage runner also works locally and in Cloud Run. Airflow calls these stages; source adapters handle formats such as GNR's Top 1,000 sample.

03 / Warehouse models

Calculate once, then serve the result.

BigQuery stores checked rows; dbt builds and tests the edition and comparison views. The API reads approved aggregate results, so the chart does not calculate pace statistics.

04 / Airflow

Coordinate without repeating the logic.

Task dependencies stop later steps when validation or an earlier build fails. Airflow records the run history; the existing Python and dbt stages still do the processing. A failed dbt build can leave views that an earlier step already created.

05 / Bounded cloud work

Use the cloud where the project needs it.

Cloud Run serves the page and runs separate export and dbt jobs; BigQuery holds the snapshots and marts. The managed Composer run was an exercise. The Composer environment was removed after verification. New historical runs are currently started manually. This small dataset does not need cloud scale, but the deployed path shows how its stages, access and evidence fit together.

Full-results path

What each dbt model represents

GNR's Top 1,000 samples use separate models and a fixed event weather window rather than individual runner weather matches.

ModelOne row means
stg_race_resultsOne candidate source result, including its validation outcome.
fct_race_resultsOne accepted result, with pace and matched weather where available.
mart_event_summaryOne edition and its counts, pace summary and weather coverage.
mart_course_comparisonOne selected edition relative to a named baseline; differences appear only when comparable.

Edition timing methods also matter: Battersea's unknown chip/gun basis leaves baseline pace changes blank.

What we verified

Two useful run outcomes

Stopped safely

Invalid configuration ended the DAG before Cloud Run.

The first task failed; all five downstream tasks were blocked. No Cloud Run job was submitted.

See the validation evidence
Safe rerun

The same Folkestone snapshot passed all six tasks again.

The loader verified the existing 459 rows and submitted no new warehouse load. That run checked an existing snapshot; it did not demonstrate a fresh insert or transactional rollback.

See the rerun evidence

Coordination

Deployments are checked, too.

Terraform records the service and its access. Immutable container images identify deployed code. CI checks code, models and containers offline; separate real-cloud runs verify the deployed stages.

Evidence today

Checks leave a trail.

We retain source hashes, validation counts, BigQuery job IDs, dbt artifacts, reconciliation results and execution logs for success and failure. These records let us check what happened at each stage.

Cloud Monitoring checks API availability and emails on sustained failure and recovery. Its dashboard shows requests, errors and latency. Data correctness comes from dbt tests and reconciliation; this page does not show live pipeline status.

See the verified alert test and troubleshooting guide

Course compatibility is checked separately. Different runners enter each edition, so the comparison does not prove that weather caused a change in pace.

Explore the comparison