Chapter 14 · ETL vs ELT Architecture: Staging, Raw, Integration, Presentation, and Transform Ownership

Immutable Raw Data, Replayability, Audit Columns, Batch IDs, Load Timestamps, and Lineage

Preserve immutable source evidence and make every replay attributable with batch IDs, load timestamps, source hashes, deterministic outputs, and explicit lineage edges.

Intermediate → Advanced125–145 minutesReplay + lineage labPython 3 stdlib + sqlite3 · local/syntheticLast reviewed: September 2026

Learning outcomes

A replay is meaningful only if the input identity is stable. If yesterday's “raw” file can be overwritten under the same batch name, an identical SQL script can produce a different answer and nobody can reconstruct which source evidence supported the published report.

01

Distinguish immutable raw evidence from parsed raw tables and downstream transformed state.

02

Attach batch IDs, source-file identity, event time, load time, transform IDs, and hashes without confusing audit metadata with business semantics.

03

Replay the same immutable batch into an independent database and compare semantic checksums.

04

Detect a raw mutation rather than silently accepting different bytes under the same batch identity.

05

Explain what a checksum proves and what correctness claims still require row/grain/metric tests.

Chapter 14 continuity contract

Chapter 14 preserves the accepted AtlasMart production state established through Chapters 11–13: eight current paid order-line facts, five paid orders, ten units, 690 USD paid GMV, 425 USD cost-at-sale, 265 USD gross profit, and the governed inventory snapshot of 137 units. Chapter 13's Q-prefixed malformed training batch remains isolated quality-test evidence. This chapter changes where transformations execute and which intermediate states are persisted; it does not silently redefine sales grain, correction history, metric formulas, or customer identity.

Execution and scope boundary

The mandatory lab is synthetic, local, and free. It uses Python 3 standard library plus its bundled sqlite3 module. Generation-time validation ran with Python 3.13.5 and SQLite 3.46.1; learners should record their own python --version and sqlite3.sqlite_version because behavior and optimizer details can vary. The lab demonstrates layering, replay, lineage, and deterministic controls—not cloud pricing, distributed exactly-once guarantees, production durability, or vendor-specific warehouse performance.

1. Immutability is an identity rule

For AtlasMart batch B20260921-001, the raw file name, exact bytes, and SHA-256 are treated as one evidence identity. A rerun may read those bytes many times, but it must not mutate them. If a producer sends corrected data, give it a new governed revision/batch identity or correction event; do not overwrite the old evidence and pretend history never changed.

raw_promotion.py
def promote_raw(landing, raw):    incoming = landing.read_bytes()    incoming_hash = sha256_bytes(incoming)    if raw.exists():        if sha256_bytes(raw.read_bytes()) != incoming_hash:            raise RuntimeError("immutable raw batch already exists with different bytes")    else:        raw.write_bytes(incoming)    return incoming_hash

2. Audit columns answer operational questions, not business-time questions

Field Meaning Do not misuse as
event_ts When the business event occurred. Load/certification timestamp.
recorded_at When the source/correction record was recorded. Dimension as-of event time unless policy says so.
batch_id Pipeline/source-delivery identity. Business transaction identifier.
source_file Raw evidence location/name. Proof that the row is correct.
load_ts When this local load wrote the row. Historical sales date.
transform_id Version/name of semantic action. Metric owner or business definition by itself.

Chapter 11 already showed why event time and load time cannot be substituted in SCD as-of joins. Layering must preserve those semantics, not flatten all timestamps into “updated_at.”

3. Deterministic replay needs canonical semantic state

A raw byte hash proves the input file is identical. An integration checksum proves the selected ordered rows are identical under a stated canonical serialization. A presentation checksum does the same for the aggregate. None proves that 690 USD is the correct business definition without the earlier grain, revision, quality, and metric contracts.

semantic_checksum.py
def canonical_hash(rows):    payload = json.dumps(rows, sort_keys=True,                         separators=(",", ":"), ensure_ascii=False)    return hashlib.sha256(payload.encode("utf-8")).hexdigest()first = load_database(raw, Path("warehouse.db"), batch_id, "dev")second = load_database(raw, Path("warehouse_replay.db"), batch_id, "replay")assert first["integration_sha256"] == second["integration_sha256"]assert first["presentation_sha256"] == second["presentation_sha256"]

Expected Chapter 14 fixture hashes after generation-time validation:

Evidence Expected SHA-256
Raw CSV bytes e59a09c3d89855c024bd6f2cf283c9b1a65aa769f8a0656e57e76e1f88dd716b
Integration semantic rows 548c4361d9071b4d5e85e2a507ec4d86b42c6c1e90bb7f2d92dedf5a63826dce
Presentation semantic rows c2516669eed256c512ad207494c0cf3086d5d2aa2262e28ae09d4795e3b73690

4. Controlled failure: mutate raw “to fix the data”

Suppose an operator opens raw O1002 revision 1 and changes 200 to 190, then deletes revision 2 because “190 is the right answer.” The presentation can still show 690, but the authorized restatement trail from Chapter 11 has been destroyed. Replaying an older report is no longer possible.

The repair is append/version semantics: preserve both revisions, let integration choose the current governed revision, and retain the correction event. The raw hash makes accidental in-place edits detectable.

5. Lineage is a graph of evidence, not a comment

The lab records edges landing file → raw file → TEMP staging → int_sales_current → mart_sales_daily, each with a transform ID. Production lineage can add columns/jobs/metrics/reports and standardized event formats, but the minimum useful question remains: “which exact upstream evidence and transformation produced this published object?”

Security applies to lineage too. Raw paths, row samples, and debug metadata can reveal sensitive context; expose only what authorized operators and consumers need.

Knowledge check

Check your understanding

  1. Why is an immutable raw hash useful?
  2. Should load_ts determine historical customer version?
  3. What does equal presentation checksum prove?
  4. Why is that checksum not enough to prove correctness?
  5. What is the minimal lineage path in this lab?
Review the answers

1. It detects byte changes under the same evidence identity and anchors replay to a specific input.

2. No; business event time does under the existing AtlasMart history policy.

3. The canonical presentation rows are identical for the two local replays.

4. Canonical serialization can faithfully reproduce semantically wrong logic; grain/metric/quality tests are still required.

5. Landing → raw → staging → integration → presentation, with explicit transform IDs.

Summary and next step

This lesson established the mechanism and production boundaries for Immutable Raw Data, Replayability, Audit Columns, Batch IDs, Load Timestamps, and Lineage while preserving AtlasMart’s declared grain, governed metrics, history, and reconciliation evidence. Continue to Transformation Modularity, Reusable Intermediate Models, Dependency Graphs, and Environment Promotion with those contracts unchanged unless an explicit, tested migration says otherwise.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.