Architecture Decision Records¶
This directory is the decision layer of data-lab. The running services prove the
infrastructure works; these records explain why it is shaped the way it is. They are the part
of the project that demonstrates architecture judgment rather than implementation — a documented
choice, the alternatives weighed, and the consequences accepted.
Why ADRs¶
An Architecture Decision Record captures one significant, hard-to-reverse decision at the moment it is made: the forces in play, the options considered, the option chosen, and the tradeoffs that come with it. The value is not the conclusion — it is the reasoning, preserved so that a future reader (including future-me, or a reviewer) can understand the decision without reconstructing it, and can tell whether it still holds when the context changes.
A decision is ADR-worthy when it is significant (it constrains later work), cross-cutting (it affects more than one component), and costly to reverse. Routine, local, or easily-undone choices do not need a record.
Conventions¶
Numbering — sequential, zero-padded, never reused: 0001, 0002, … The number is an
identifier, not a priority.
Status lifecycle — every ADR carries one of:
| Status | Meaning |
|---|---|
proposed |
Drafted, not yet ratified. Open for revision. |
accepted |
In force. This is how the system is built. |
superseded by ADR-XXXX |
Replaced by a later decision. Kept for history. |
deprecated |
No longer relevant, but not directly replaced. |
Immutability — an accepted ADR is not edited to change its decision. If the decision
changes, write a new ADR that supersedes it and update the old one's status. The history of
decisions is itself information; rewriting it destroys that.
Index¶
| ADR | Title | Status |
|---|---|---|
| 0001 | Single-node Docker Compose, no orchestrator | accepted |
| 0002 | Traefik v3 as the edge reverse proxy with automatic TLS | accepted |
| 0003 | Direct public exposure on a Hetzner VPS over Cloudflare Tunnel | accepted |
| 0004 | HTTP-01 over DNS-01 for ACME certificate issuance | accepted |
| 0005 | Monorepo with per-project plug-in to a shared CI/CD pipeline | accepted |
| 0006 | Scheduled micro-batch as the media pipeline's default path, streaming built as the priced alternative | accepted |
| 0007 | The streaming side is poll-fed, and we say so | superseded by ADR-0015 |
| 0008 | Redis Streams as the broker; no Kafka | accepted |
| 0009 | Ephemeral comparisons as in-process run windows, not container spin-ups | accepted |
| 0010 | Public triggers are rate-limited, capped, and shared | accepted |
| 0011 | Same-origin /api on the apex: the one exception to the flat-subdomain scheme |
accepted |
| 0012 | Minimal dbt: a contract and four models, no medallion ceremony | proposed (accept in CP13) |
| 0013 | Postgres + DuckDB dual engine, and what makes the benchmark fair | proposed (accept in CP13) |
| 0014 | Exhibit resource numbers come from Prometheus, not a bespoke agent | accepted |
| 0015 | Wikimedia EventStreams + Hacker News replace Twitch as the media pipeline's data sources | accepted |
Note: ADRs 0001–0005 record decisions already implemented and locked during CP1–CP4; they were written up (retroactively, as is normal for foundational choices) and added to this index during the CP9 documentation pass. ADR-0006, 0008–0010, and 0014 were accepted in CP10 once CP10.1–10.4 had actually implemented and live-verified each decision (batch/streaming both live, Redis Streams as the broker, in-process Redis-backed run windows, rate limiting, Prometheus reuse) — none needed their figures changed from proposal to implementation, only the status flip.
Note: Twitch developer-console registration was confirmed permanently blocked (Morocco) after CP9 shipped. ADR-0015 replaces Twitch with Wikimedia EventStreams (CP10's batch/streaming substrate) and the Hacker News API (CP12's sync/async substrate); ADR-0007, whose entire premise was a property of Twitch specifically, is superseded by it.