Skip to content
ExponaBLOG
APACHE SPARK & DATA ENGINEERING · DAY 029 / 100

Data lakes, warehouses and lakehouses: a practical guide

Where analytics data lives.

Expona Admin6 min read

The storage dilemma

Every data team eventually faces the same question: where do we actually store our data? You might start with a data lake because it's cheap and flexible, migrate to a warehouse for better query performance, then realize you need both. This article walks you through data lakes, warehouses and lakehouses: a practical guide to help you understand the tradeoffs and build a storage architecture that matches your team's real needs.

Understanding the three approaches

The fundamental differences between these storage patterns come down to what problem each solves. Think of them as different responses to the same basic challenge: you have raw data coming in, analysts need to query it, and you want to control costs.

Data lakes: flexibility and scale

A data lake is fundamentally cheap object storage—typically S3, GCS, or ADLS—where you dump data in any format: JSON, Parquet, CSV, binary blobs, unstructured documents. The appeal is immediate: storage is inexpensive at scale, you're not forced to normalize data upfront, and you can experiment with different schemas as requirements evolve.

The classic scenario: your backend team is publishing raw events to S3 every hour, your ML team needs access to historical user interactions for feature engineering, and your product team wants to explore some exploratory analysis without waiting for a schema design meeting. A data lake handles all three use cases without forcing you to agree on structure first.

But lakes have real pain points. Query performance degrades quickly as data volume grows. There's no built-in ACID guarantees, so concurrent writes can corrupt data. Schema enforcement happens at read time (or not at all), making it easy to accidentally break downstream pipelines. You end up with "data swamps"—lakes that nobody understands or trusts.

Data warehouses: structured and performant

A data warehouse like Snowflake, BigQuery, or Redshift is the opposite bet. Data must conform to a predefined schema before it lands. The system is optimized for analytical SQL queries, offering fast columnar storage, query optimization, and built-in cost management. Most importantly, warehouses guarantee ACID transactions and data quality.

The typical setup: you have an ETL pipeline that validates, transforms, and loads data into dimension and fact tables. Your BI tool connects directly to the warehouse and runs dashboard queries in milliseconds. Access control is granular. Costs are predictable and often cheaper per query than a lake because storage and compute are optimized together.

The tradeoff is rigidity. Every schema change requires planning. Early-stage data exploration is expensive because you're running queries on premium infrastructure. Unstructured data (images, logs, PDFs) doesn't fit well. If your requirements change, refactoring the warehouse schema is painful.

Lakehouses: the hybrid approach

A lakehouse combines lake storage (cheap, flexible, scalable) with warehouse features (ACID transactions, schema enforcement, SQL optimization). Open table formats like Delta Lake, Apache Iceberg, and Apache Hudi sit on top of object storage and add transaction logs, schema validation, and versioning.

Example: you store raw Parquet files on S3. On top of that, you add Delta Lake, which introduces a transaction log that tracks every change. Now you can:

  • Run concurrent writes without corruption
  • Enforce schema at write time
  • Query via standard SQL (using Spark, Presto, or DuckDB)
  • Time-travel to previous versions of data
  • Still pay lake-level storage costs

Lakehouses work best when you want exploration flexibility but also need data reliability. They're particularly strong for modern data stacks where Spark is already in the picture.

Comparing the three: strengths at a glance

Aspect Data Lake Data Warehouse Lakehouse
Storage cost Very cheap Moderate to high Very cheap
Query performance Poor at scale Excellent Good to excellent
Schema flexibility High Low High
Data quality Weak Strong Strong
ACID transactions No Yes Yes (with format)
Learning curve Low Moderate Moderate to high

Open table formats: Delta, Iceberg, and Hudi

If you're considering a lakehouse, you'll need to pick a table format. All three bring transaction logs and schema management to object storage, but they have different philosophies and maturity levels.

Delta Lake

Delta Lake (by Databricks) is the most mature and widely adopted. It writes a JSON transaction log to a hidden _delta_log directory alongside your data files. Every write creates a new log entry, and readers consult the log before accessing files.

Delta is deeply integrated with Apache Spark and works well in Python and Scala environments. It supports time-travel, schema evolution, and compact file management.

python
from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("DeltaExample").getOrCreate()

# Write data to Delta format
df = spark.read.option("inferSchema", "true").csv("raw_events.csv")
df.write.format("delta").mode("overwrite").save("s3://my-bucket/events")

# Read with time-travel
df_old = spark.read.format("delta").option("versionAsOf", 5).load("s3://my-bucket/events")

# Show history
spark.sql("DESCRIBE HISTORY delta.`s3://my-bucket/events`").show()

Apache Iceberg

Iceberg (originally from Netflix) takes a different approach: the metadata is versioned separately from data files, and schema changes are first-class operations. It's designed for performance at very large scale and has excellent support across tools (Spark, Presto, Trino, DuckDB).

Iceberg is language-agnostic and tends to be the choice when you're running a polyglot data platform. It also handles partition evolution more elegantly than Delta.

Apache Hudi

Hudi (from Uber) focuses on incremental processing and near-real-time updates. It supports both copy-on-write and merge-on-read storage, making it strong for streaming ingestion and GDPR-style deletions.

Hudi is the right choice if your use case involves frequent small updates or you need to handle deletions efficiently. It's more complex to operate than Delta or Iceberg.

In practice: most teams starting out choose Delta because it's simpler and tightly integrated with Spark. As you scale and need cross-tool compatibility, Iceberg becomes attractive. Hudi is more specialized and worth learning only if incremental updates are core to your pipeline.

Choosing your storage by needs

Cost-first teams

If your primary constraint is budget, start with a data lake. Pay for storage only, ingest everything, and query sparingly. This works if you have a small analytics team or you're still figuring out what data matters. The risk: technical debt accumulates, and at some point the "swamp" becomes unmaintainable.

Query-performance-first teams

If you run dozens of BI dashboards and query latency directly affects user experience, invest in a warehouse. Pay more upfront, gain predictable performance and built-in governance. This is the right call for mature products where analytics is mission-critical.

Flexibility-plus-reliability teams

A lakehouse makes sense if you need to experiment rapidly but also can't afford data corruption or broken pipelines. Common scenario: you're moving from a single warehouse to a modern data stack with multiple tools (Spark, dbt, Presto) and need them to work together seamlessly.

Hybrid approach: the reality

In practice, most teams end up running both. Raw events land in a data lake (S3 + Delta Lake or Iceberg). A scheduled Spark job transforms and loads clean data into a warehouse or a curated lakehouse layer. BI tools query the warehouse. Data scientists pull raw data from the lake into notebooks.

This dual approach gives you the best of both worlds: cheap storage for experiments and raw data, plus fast, reliable queries for production analytics.

Common mistakes

  • Treating a lake as a warehouse: Adding more schema validation and governance after the fact is expensive. If you know you need structure and speed, start with a warehouse or a well-designed lakehouse from day one.
  • Over-engineering the lakehouse: Not every project needs Delta Lake or Iceberg. If your data is small and changes rarely, a simple S3 + Parquet setup is faster to build.
  • Ignoring the operational burden: Open table formats add complexity. You need to understand transaction logs, compaction, and schema evolution. Budget time for learning and monitoring.
  • Assuming warehouses are expensive: Modern cloud warehouses like BigQuery and Redshift are efficient for analytical workloads. Don't dismiss them based on legacy pricing models.
  • Mixing raw and processed data in the same layer: Keep raw ingestion separate from curated analytics. This prevents bugs from cascading and makes troubleshooting easier.

Key takeaways

  • Data lakes are cheap and flexible but lack structure; warehouses are performant and reliable but rigid; lakehouses combine the benefits of both.
  • Open table formats (Delta Lake, Iceberg, Hudi) bring warehouse-like guarantees to object storage, enabling lakehouse architectures.
  • Choose your storage pattern based on your team's priorities: cost, query performance, flexibility, or some combination.
  • Most mature data teams run hybrid architectures—raw data in a lake, curated data in a warehouse or lakehouse layer.
  • Start simple. Add complexity only when you have a concrete problem it solves.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles