ADR-0012 — Minimal dbt: a contract and four models, no medallion ceremony¶
- Status: proposed (accept in CP13)
- Date: 2026-07-02
- Domain: transformation layer · scope discipline
Context¶
The project's governing rule: an architecture choice is showcased only when a viewer can observe its tradeoff against the rejected alternative. A full bronze/silver/gold medallion build shows no tradeoff — it is backdrop, not exhibit. But two pieces of the transform layer are genuinely load-bearing: the bronze contract (without a shared event shape, the batch-vs-streaming comparison compares apples to oranges) and a dedup/cleaning step (benchmarking engines on dirty, double-observed data would make Comparison 3's numbers meaningless).
Decision¶
Keep exactly what carries weight:
- The bronze contract (
docs/contracts/media-bronze-contract.md) — non-negotiable. - A minimal dbt project, four models (per ADR-0015's dual-source pivot, still within CLAUDE.md
M5's 3–4 model bound): one staging model per source —
stg_wiki_edits,stg_hn_snapshots(dedup, typing) — feeding two narrow aggregates, no separate fact layer for either (there isn't enough shape between staging and aggregate here to earn one):agg_wiki_edit_rate_hourly(the rolling-window aggregate that is the primary benchmark query — chosen over HN engagement for volume: EventStreams reaches useful scale in days, HN's 15-minute snapshot cadence accumulates far more slowly) andagg_hn_engagement_daily(score/comment-velocity deltas — the mutable-fact narrative example, not the benchmarked table). Schema tests (unique,not_null) on the keys. Run as an ephemeral container (make dbt-run), zero steady-state RAM.
No named gold layer, no exposure docs, no snapshot machinery. dbt is here for two reasons only: it is the honest home for the cleaning logic, and its visible presence is recruiter-legible evidence of standard tooling. Both are served by three models.
Consequences¶
- The transform layer costs one task of setup and nothing at runtime.
- Comparison 3 gets a fair, deduplicated input, and its query lives in version control as a tested model rather than a string in application code.
- If the project later earns a real gold layer, the structure extends without rework — the restraint is reversible; gold-plating up front would not have been.
Alternatives considered¶
- Full medallion + dbt docs/tests suite — rejected: decoration by the project's own rule.
- Plain SQL in the poller, no dbt — viable and leaner; rejected because the cleaning logic deserves tests and lineage, and the tool's presence is cheap at this scope.