Traditional data warehouses coupled compute and storage on the same nodes. Running a large query required buying more hardware: more CPU and more storage together, even if you only needed more CPU for a week. Compute-storage separation decouples them: data lives in cheap object storage (S3, GCS, Azure Blob), and compute clusters spin up on demand to query it. Pay for compute only while queries run. Scale each dimension independently.
A row-oriented database stores each row contiguously: all columns for row 1, then all columns for row 2. This is optimal for OLTP workloads that read or write one row at a time. Analytics queries read one or two columns across millions of rows: “sum of revenue where region = ‘us-east’.” Row storage forces you to read every column of every row to compute this, even though you only need two.
A data warehouse ingests raw events from production systems and transforms them into queryable datasets for analytics. The transformation pipeline has stages: raw ingestion, cleaning and normalization, business-level aggregation. Medallion architecture names these stages: bronze, silver, gold. The naming is less important than the principle: each layer has a contract about data quality, and data only flows forward.
Bronze: Raw and Immutable Bronze is append-only raw data exactly as it arrived from the source: JSON payloads from Kafka, CSV exports from operational databases, API responses.
You add a new derived field to your user profiles: “days since last purchase.” You can compute it for new events going forward. But existing users already have purchase history. You need to compute this field for all existing users retroactively. That’s a backfill.
Backfills happen constantly in production systems. They’re more disruptive than they look.
The Basic Problem You have a dataset of 500 million user records. You need to reprocess all of them to compute the new field.