Chapter 3 — Key Takeaways (Data Architecture Principles)
The page for a design review. Print it and put it on the table.
The definition
A decision is architectural to the extent that it is expensive to reverse.
It is a spectrum, not a category. Rank your decisions by reversal cost and spend deliberation at the top.
| Decision | Reversal cost |
|---|---|
| Cloud provider | 1–2 years |
| Warehouse vs. lakehouse as primary store | 6–12 months |
| Partitioning scheme on largest tables | 1–3 months |
| Batch vs. streaming for a pipeline | 1–2 months |
| Dimensional grain | 1–2 months |
| Orchestrator | 2–4 weeks |
| Transformation framework | 2–4 weeks |
| File format | 1–2 weeks |
| Compression codec | hours |
| BI tool | days–weeks |
The real work is pushing decisions DOWN this table. Bronze in Parquet turns "which warehouse" from a 12-month decision into a 3-month one. Under uncertainty, optimize for reversibility, not correctness.
Batch vs. streaming
Wrong question: how fresh does it need to be? (Answer is always "as fresh as possible.") Right question: what decision or action changes if this is an hour old instead of a minute old?
| Answer | Build |
|---|---|
| "Nothing, but it feels better" | Batch. Run it hourly if the anxiety is real. |
| "I'd catch a problem sooner" | Monitoring and alerting, not a pipeline |
| "An automated system acts on it" | Streaming — this is the real case |
daily batch → hourly batch → micro-batch (1–15 min) → streaming (<1s)
simplest, cheapest, easiest to backfill ──────────▶ hardest on every axis
What streaming costs beyond latency: always-on infrastructure · backfills become genuinely hard · state must survive restarts · event time ≠ processing time · you must define a watermark policy to even say what "correct" means · debugging against a moving offset.
At Kestrel's clickstream volume: streaming ≈ $900/month vs. hourly micro-batch ≈ $96/month. ≈9× metered — and the metered part is the smaller cost.
ETL vs. ELT
ELT won because prices changed, not because practice improved. Coupled expensive storage+compute made transform-first rational; $0.023/GB-month storage and elastic compute inverted it.
ETL is still correct in exactly three cases:
- You legally may not land the raw data (PCI, health identifiers, residency).
- Volume reduction is enormous and the raw genuinely worthless.
- The source can be read only once.
Not on the list: "the data is messy," "we don't want junk in the warehouse," "our warehouse is expensive." Those argue for layering, not for discarding evidence.
Warehouse vs. lake vs. lakehouse — by guarantee, not by product
| Warehouse | Lake | Lakehouse | |
|---|---|---|---|
| Schema enforcement | on write | none | on write, evolvable |
| ACID transactions | yes | no | yes |
| Row-level delete | yes | rewrite the file | yes |
| Time travel | sometimes | no | yes |
| Storage cost | higher | lowest | lowest |
| Semi/unstructured | poor | excellent | good |
| Engine independence | low | total | high |
| Operational burden | lowest | low* | highest |
| Maturity | decades | decades | years |
* discipline-dependent — the failure mode is a data swamp
⚠️ A directory of Parquet files is not a table. Two concurrent writers to one S3 prefix interleave silently; a reader that lists mid-write gets a partial result and does not error. That guarantee is exactly what a table format adds.
Three questions that choose: (1) structured with known query patterns? → warehouse. (2) semi-structured, or multiple engines need it? → files in object storage. (3) need transactions, updates, or time travel over those files? → lakehouse.
Kestrel: lakehouse for bronze/silver, warehouse for gold. Not a compromise — each layer using what fits its access pattern.
Sizing
| Strategy | Annual cost | SLA |
|---|---|---|
| Fixed at peak (48 nodes) | $63,072 | met |
| Fixed at average (8 nodes) | $10,512 | missed on peak days |
| Elastic (8 for 355 d, 48 for 10 d) | $11,952 (19.0% of peak) | met |
The cloud is not cheaper than owning hardware. It is cheaper than owning hardware sized for your peak. Flat, predictable load may genuinely be better off owned.
$$L = \lambda W \qquad \text{items in system} = \text{arrival rate} \times \text{time in system}$$
At 2,900 events/sec × 40 ms = 116 concurrent handlers needed. Size on the tail (p99), not the mean — the queue builds during slow requests and never drains.
The six surviving principles
- Choose common components for interoperability and hiring pool, not peak capability.
- Plan for failure — ask the blast radius and how the system behaves while broken.
- Architect for scalability in both directions. A system that cannot shrink pays peak prices forever.
- Build loosely coupled systems. In data, coupling hides in unpublished intermediate tables that quietly became interfaces.
- Make reversible decisions.
- Security and cost are design inputs, not afterthoughts. Both are cheap to build in and expensive to add.
The ADR — one page, seven sections
# ADR-NNN: Title
Status / Date / Deciders
## Context what forced the decision, with numbers
## Decision what was chosen, in one or two lines
## Alternatives considered each with WHY IT WAS REJECTED
## Consequences + and −, honestly
## What would reverse this ← the most valuable section
## Review date
The three sections people omit: alternatives with reasons, what would reverse this, and a review date.
Reversal conditions must be observable. ✗ "if requirements change" ✓ "if bronze exceeds 2 TB"
Also worth stealing: name the decision most likely to be wrong, inside the document.
Three questions to ask before any storage decision
- Does any of this data identify a person, directly or in combination?
- If someone requests erasure, what is the procedure and how long does it take?
- Is there a retention limit we must honor, and what enforces it?
Ten minutes, asked before the benchmarks. At Kestrel, question 2 eliminated an entire option that cost analysis and performance benchmarks had both favored.