This topic is the architecture of the analytical stack — the systems an organisation builds to query “what happened”, “what’s happening”, and “what will happen” with data from many sources.
The Historical Evolution
| Generation | Date | Shape |
|---|---|---|
| Standalone reports | 1970s-1980s | Queries against the operational database |
| Data warehouses (DWH) | 1990s | Separate analytical database (Teradata, Oracle EBS) — loads (ETL) from operational sources |
| Big Data / Hadoop | 2000s | Software (Hadoop) on commodity hardware — schema-on-read, large raw-data stores |
| Cloud lake + warehouse | 2010s | S3 + Snowflake / BigQuery / Redshift — separation of storage and compute |
| Lakehouse | 2020s | Open table formats (Iceberg, Delta, Hudi) that enable warehouse guarantees on top of object storage |
The current consensus architecture is a lakehouse — file store of open formats underneath, query engines on top — but the historical design debate still informs each organisation’s shape.
Kimball vs Inmon
Two philosophies of data warehouse architecture, each named after its originator:
| Dimension | Kimball (dimensional) | Inmon (normalised) |
|---|---|---|
| Top shape | Bottom-up — marts for one business process at a time | Top-down — one normalized enterprise warehouse, marts drawn off |
| Internal model | Star schema (fact + dimensions) | 3NF inside the warehouse; star schemas in downstream marts |
| Time-to-first-value | Fast — first mart in weeks | Slow — enterprise warehouse before value flows |
| Reusability | Marts accumulate; some grinding over shared dims | High — one model, every mart consumes it |
| Common pitfall | Conflicting dimension definitions across marts | Long project that delivers nothing for years |
The practical reality: most modern data platforms are Kimball-shaped at the consumption end (semantic layer reads from star-schema models) and Inmon-shaped at the data foundation (raw data normalised into a “clean” Bronze/Silver layer). The two are complementary, not exclusive.
Data Warehouse vs Data Lake
| Property | Data Warehouse | Data Lake |
|---|---|---|
| Storage shape | Relational tables | Files (Parquet, JSON, CSV) |
| Schema | Schema-on-write | Schema-on-read |
| Engine | Proprietary (Teradata, Snowflake, BigQuery) | Open (Spark, Trino, Flink, custom) |
| Workload | SQL-heavy analytics; well-understood queries | Ad-hoc — including ML training, full-text search, low-level data science |
| Cost | Compute-bound; expensive at scale | Storage-bound; cheaper at scale |
| Risk | Brittle to schema change; central bottleneck | Becomes a “data swamp” — nobody knows what’s in it |
Each has its characteristic failure mode: the warehouse’s is strictness ossifying schema creation; the lake’s is chaos preventing reuse. The lakehouse is the synthesis that aims for both.
The Lakehouse
A lakehouse is the architecture that puts warehouse guarantees on top of lake storage:
Query engine (Spark, Trino, Snowflake, ...)
↓
Open table format (Iceberg / Delta / Hudi)
↓
┌──────────────┴───────────────┐
│ Object storage (S3, GCS) │ ← table data in Parquet / ORC
└───────────────────────────────┘
The three properties that distinguish it from raw S3-with-Parquet files:
- ACID transactions — multi-table writes are atomic via a snapshot mechanism. Inserting five files partitioned across two tables either all commit or all roll back.
- Schema management — the table format tracks schema history; you can time-travel to the table as of
2024-03-12 10:00:00. - Catalog integration — a metastore (Hive Metastore, Glue Catalog, Unity Catalog, Nessie) provides SQL-discoverable table names.
The data lives in object storage (cheap, durable, write-once). The metadata lives in the table format (snapshot history, manifest of data files). The query engine reads the manifest, prunes files by predicate, scans only relevant Parquet files.
Iceberg, Delta, Hudi
Three open table formats dominate:
| Format | Origin | Distinct feature |
|---|---|---|
| Apache Iceberg | Netflix (now Apache) | The cleanest separation between catalog, manifest, and data — the format with the broadest engine support (Trino, Spark, Flink, Snowflake, BigQuery) |
| Delta Lake | Databricks | Tight Spark integration; “Delta” SQL extensions; strong adoption on Azure Databricks |
| Apache Hudi | Uber (now Apache) | Strong support for upsert workloads; primary-key indexing — the right fit for change-data-capture streams |
Each is technically interchangeable; the choice is downstream of the ecosystem you’ve standardised on. Iceberg has the broadest engine support; Delta has the smoothest Databricks experience; Hudi is the right call for streaming-heavy workloads with upsert semantics.
ETL vs ELT
| Pattern | When | Tooling |
|---|---|---|
| ETL (extract-transform-load) | Transformations happen outside the warehouse, in the loading pipeline | dbt at the warehouse, Airflow outside it |
| ELT (extract-load-transform) | Raw data lands first; transformations run inside the warehouse on the loaded raw data | Snowflake + dbt; BigQuery + dbt |
The cloud warehouse made ELT dominant: storage is cheap enough to land raw, compute is idle enough that transformations can run as SQL inside the warehouse, and the analytics engineer is more productive writing SQL than writing Python pipelines.
The shift to ELT pairs naturally with tools like dbt — a SQL-first transformation layer that runs as queries, with tests and lineage. The transformation step is the warehouse’s job; the warehouse’s strength is exploited, not avoided.
Practice Trajectory
- Pick an analytical pipeline in your organisation. Identify which steps would today be ETL vs ELT; identify which would benefit from the shift.
- Sketch a Bronze / Silver / Gold lakehouse architecture for clickstream + payments. Name the open format at each layer; explain what each layer’s contract is.
- Pick a current “data swamp” problem in your stack. Identify which lakehouse property (ACID, schema history, catalog discoverability) would mitigate it most.
- Compare costs: storing 10TB warehouse-native vs S3-lakehouse. Where does the trade-off tip — at what table size, query frequency, or freshness requirement?
- Run
dbtagainst a small dataset; identify one test, one model, and one lineage graph edge. Note what becomes visible that wasn’t before.
When It’s the Right Tool
| Situation | Takeaway |
|---|---|
| Central analytics for an enterprise | Lakehouse with open table formats; separates storage and compute |
| Small data, SQL-first analytical team | Cloud warehouse (Snowflake / BigQuery); the lakehouse buys little |
| Streaming-first with CDC upserts | Hudi or Iceberg with merging; native upsert support matters |
| “We do ETL in Spark and load to warehouse” | Consider ELT — let the warehouse run transformations |
| Long-running ETL batch failures | Lakehouse with ACID lets the load resume mid-batch cheaply |