Data Warehouse vs Data Lake vs Lakehouse

Warehouses, lakes and lakehouses are three answers to the same question: where should analytical data live and how should it be queried? This page traces how each arose, what actually differs underneath, and how to choose.


1. The Three Architectures in One Paragraph Each

A data warehouse is a database designed for analytics: data is cleaned and modelled before loading (schema-on-write), stored in a format the engine controls, and queried with SQL. It is fast, consistent and well governed, but storage is tied to one vendor and unstructured data such as images or logs fits poorly.

A data lake is cheap storage — originally HDFS, now object stores such as Amazon S3, Azure Data Lake Storage or Google Cloud Storage — holding files in open formats (Parquet, ORC, JSON, CSV, images). Structure is applied when data is read (schema-on-read). It is flexible and inexpensive but lacks transactions, so concurrent writers corrupt tables, and without discipline it decays into a "data swamp".

A lakehouse keeps the lake's open files on object storage and adds a table format — Delta Lake, Apache Iceberg or Apache Hudi — that records which files make up each table version in a transaction log. That log brings ACID transactions, schema enforcement, time travel and efficient metadata to plain files, so warehouse-style SQL and machine learning can share one copy of the data.

2. Why the Distinction Matters

The choice decides where your data physically lives, which engines can read it, how much you pay, and how governance is enforced. Teams that ran a lake for data science and a warehouse for BI often maintained two copies of the same data with separate pipelines that drifted apart. The lakehouse pitch is to remove that duplication. At the same time, cloud warehouses such as Snowflake and BigQuery now read and write Iceberg tables, so the boundary is blurring: the more useful question today is "which open format and catalog, and which engines on top?"

For learners, the three terms are also a good map of the history of data engineering. Most job descriptions, tools and interview questions assume you can explain why each generation appeared, what problem it solved, and what new problem it introduced. Understanding that chain makes vendor marketing much easier to read critically.

3. How It Works: Evolution, Storage and Compute

Evolution of analytical storage Data Warehouse 1990s - : Teradata, Oracle later Redshift, BigQuery, Snowflake Data Lake 2010s - : HDFS, then S3/ADLS Hive, Spark, schema-on-read Lakehouse 2020s - : Delta, Iceberg, Hudi warehouse features on lake files Each step kept the previous one's strengths and attacked its main weakness.

Warehouses (Inmon and Kimball designs from the 1990s) ran on expensive appliances where storage and compute scaled together. Hadoop made storage cheap and moved computation to the data, but early Hive tables were just directories: no atomic updates, no deletes. Cloud object storage then separated storage from compute entirely, and table formats added the missing database guarantees on top.

Three architectures side by side Warehouse SQL engine proprietary storage managed tables BI / SQL Lake Spark / Hive / Presto Parquet, CSV, JSON object storage ML, data science Lakehouse any engine: Spark, Trino table format (ACID log) Parquet on object store BI + ML on one copy

The diagram shows the key structural difference. In a warehouse one engine owns the stack. In a lake any engine can read the files, but nothing coordinates writers. In a lakehouse the table format is the coordination layer: a commit atomically swaps in a new metadata snapshot listing data files, so readers always see a consistent version. Statistics in that metadata (min/max per column per file) let engines skip files, recovering much of a warehouse's query performance.

Separation of storage and compute is now common to all three in the cloud: Snowflake, BigQuery and Redshift RA3 keep data in object storage internally and scale virtual compute clusters independently. The real difference is whether the storage format is open (readable by other engines without export) or proprietary.

Governance differs too. Warehouses provide role-based access, row and column security and auditing inside the engine. On a lake, permissions are on files and buckets, which is too coarse for "analysts may not see the SSN column". Lakehouses push governance into a catalog (Unity Catalog, Apache Polaris, AWS Glue with Lake Formation) that every engine consults, so one policy applies to Spark, Trino and SQL warehouses alike.

4. Worked Example: Lakehouse Tables with Spark and Delta

Lake files alone cannot do an atomic upsert; with a table format they can. This PySpark snippet (Delta Lake 3.x, pip install delta-spark) creates a table, merges changes and reads an older version.

from pyspark.sql import SparkSession
from delta import configure_spark_with_delta_pip

builder = (SparkSession.builder.appName("lakehouse-demo")
    .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension")
    .config("spark.sql.catalog.spark_catalog",
            "org.apache.spark.sql.delta.catalog.DeltaCatalog"))
spark = configure_spark_with_delta_pip(builder).getOrCreate()

spark.createDataFrame([(1, "alice", 10.0), (2, "bob", 20.0)],
                      "id INT, name STRING, balance DOUBLE") \
     .write.format("delta").mode("overwrite").save("/tmp/lh/accounts")

spark.createDataFrame([(2, "bob", 25.0), (3, "carol", 5.0)],
                      "id INT, name STRING, balance DOUBLE") \
     .createOrReplaceTempView("updates")

spark.sql("""
  MERGE INTO delta.`/tmp/lh/accounts` t
  USING updates u ON t.id = u.id
  WHEN MATCHED THEN UPDATE SET *
  WHEN NOT MATCHED THEN INSERT *
""")

spark.read.format("delta").load("/tmp/lh/accounts").show()          # 3 rows, bob = 25
spark.read.format("delta").option("versionAsOf", 0) \
     .load("/tmp/lh/accounts").show()                                 # original 2 rows

Look inside /tmp/lh/accounts: Parquet data files plus a _delta_log/ folder of JSON commits. That folder is the whole difference between a lake directory and a lakehouse table.

Medallion layout in a lakehouse Sources apps, CDC, files Bronze raw, append-only Silver cleaned, conformed Gold marts, features BI ML One catalog governs all three layers (Unity, Polaris, Glue, Nessie).

Most lakehouses organise tables in a medallion layout. Bronze keeps raw ingested data for replay, silver holds cleaned and de-duplicated entities, and gold contains business-level aggregates and feature tables. Quality gates between layers are where tools such as Great Expectations or dbt tests run.

5. Comparison and When to Use Each

AspectWarehouseLakeLakehouse
SchemaOn write, enforcedOn read, optionalOn write, enforced, evolvable
Storage formatProprietary (mostly)Open filesOpen files + open table format
TransactionsFull ACIDNoneACID per table
Data typesStructured, semi-structuredAnythingAnything; tables for structured
Main usersAnalysts, BIData scientists, engineersBoth
Performance tuningMostly automaticManual (file layout)Compaction, clustering, statistics
GovernanceIn-engine, matureBucket/file levelCatalog-based, maturing
Best whenSQL-centric team, managed simplicityCheap archive, raw ML dataMixed BI + ML, multiple engines, avoid lock-in

Rules of thumb: a small analytics team with mostly SQL workloads is usually happiest with a managed warehouse. A lake alone remains fine as a landing zone and archive. When you need several engines on the same data, large ML workloads next to BI, or freedom to change vendors, pick a lakehouse table format and a catalog first, then choose engines.

6. Pitfalls

8. Further Reading