◐ ai-teacher

🧱 Foundations · Chapter 8

Table formats: Delta, Iceberg, Hudi

A folder of Parquet files is not a table. It has no idea which files are current, who is writing, or what it looked like yesterday. A table format is the small ledger that answers all three.

Study this lesson free in the app →

The basics

A table format is a metadata layer that sits beside a set of data files (almost always Parquet) on object storage and defines exactly which files make up the table right now. The three open ones are Delta Lake, Apache Iceberg and Apache Hudi.

The problem it solves: object storage can't edit a file in place or rename a folder atomically. So on a plain lake, a reader can see half a write, two writers can clobber each other, an UPDATE means hand-rewriting files, and there's no "yesterday's version". Table formats fix this by never changing data files — they write new files and then atomically commit a new metadata version that points at them.

The mental model: a bank passbook. The money (data files) sits in the vault; the passbook (metadata log) says what you own. Each transaction is a new line. Reading an old line is time travel. If two clerks write at once, only one line can be next — the other retries.

Words you must know 5

Snapshot
the full list of files at one version
Commit
atomically publishing a new snapshot
Copy-on-write (CoW)
rewrite affected files on update
Merge-on-read (MoR)
write small delete/log files, merge them when reading
Compaction
rewriting many small files into fewer large ones

Explained

Delta, Iceberg and Hudi solve the same core problem — ACID tables on object storage — and they converge more every year.

What interviewers probe is how each one tracks files, because that explains everything else: concurrency, time travel, partitioning, and why your table got slow.

The passbook, not the vault

Your money in a bank isn't stored in your name on each note. The vault holds notes; your passbook records what's yours.

Withdraw ₹500 and nobody shreds notes in front of you — a new line is written. Want to know your balance on 1 March? Read up to that line.

Two clerks can't both write line 47. The second one sees line 47 is taken, re-checks your balance, and writes line 48.

And once a year the bank archives very old passbook pages — after that, you can't ask about 2019. Data files are the notes. The table format is the passbook.

What all three give you

The differences are in how metadata is laid out and what each was optimised for.

How each one tracks files

DELTA LAKE                    ICEBERG                       HUDI
_delta_log/                   catalog (Glue/REST/Hive/Nessie)  .hoodie/ timeline
 000…000.json                   └─► current metadata.json     instants:
 000…001.json  add/remove        └─► snapshot               20260314.commit
 …                                └─► manifest list (avro)    …deltacommit
 000…010.checkpoint.parquet         └─► manifests (avro)      …compaction
                                        file + partition      …clean
Commit = write next                     + column stats      base files (parquet)
numbered JSON (put-if-absent)       └─► data + delete files  + log files (MoR)
                              Commit = atomic swap of the    Commit = complete an
                              catalog's metadata pointer     instant on the timeline

The differences that matter

Delta Lake (Databricks, Linux Foundation) — ordered JSON commit log plus Parquet checkpoints. Deepest Spark/Databricks integration: OPTIMIZE, Z-ORDER, liquid clustering, deletion vectors (MoR-style deletes), change data feed. Renaming/dropping columns needs column mapping enabled. UniForm can expose Delta tables as Iceberg.

Apache Iceberg (Netflix) — tree of metadata → manifest list → manifests, committed by swapping a pointer in a catalog. Hidden partitioning (days(ts), bucket(16, ride_id)): users filter on ts, Iceberg prunes — no ride_date column to remember. Partition evolution without rewriting old data. Columns tracked by ID, so renames are safe. CoW or MoR with position/equality delete files. The widest engine support (Spark, Trino, Flink, Snowflake, BigQuery, Athena…).

Apache Hudi (Uber) — built for upserts and incremental pulls. Timeline of instants; record keys plus an index to find which file holds a key. CoW or MoR tables (Parquet base + Avro log files, compacted asynchronously). Native incremental queries: "rows changed since commit X".

At scale: what slows tables down

Small files. Streaming writes every minute → thousands of tiny files and a bloated metadata layer. Schedule compaction (OPTIMIZE / rewrite_data_files / Hudi clustering & compaction).

Delete-file buildup (MoR). Fast writes, but each read merges deletes/logs. Without regular compaction, reads get slower every day.

Snapshot buildup. Every commit adds metadata and keeps old files. Expire snapshots (expire_snapshots, VACUUM) — this is also what makes deletion requests actually remove data.

Concurrent writers. Optimistic concurrency means two MERGEs touching the same files conflict and one retries. Design writers to touch disjoint partitions, or serialise them.

Choosing: on Databricks → Delta. Multi-engine / vendor-neutral / Snowflake + Spark + Trino sharing tables → Iceberg. Heavy record-level upserts from CDC with incremental consumers → Hudi is purpose-built (though Delta and Iceberg handle CDC MERGE well too).

Gotchas

Never edit files — add files, then commit a pointer.

Delta: numbered JSON log. Iceberg: catalog → metadata → manifests. Hudi: timeline + record index, upsert-first. CoW pays on write, MoR pays on read.

Words to know

Table formatMetadata layer that tracks which data files form a table at each version, giving ACID semantics.
SnapshotThe complete set of live data files at one table version.
Optimistic concurrencyWriters proceed without locks and check for conflicts at commit time, retrying if needed.
Copy-on-writeUpdates rewrite whole affected data files; reads stay simple and fast.
Merge-on-readUpdates write small delete or log files that readers merge; compaction folds them in later.
Hidden partitioningIceberg derives partitions from column transforms so queries prune without referencing a partition column.
Time travelQuerying the table as of an earlier snapshot or version.

In two minutes

Test yourself

1. How does a Delta Lake commit become atomic?

  1. It locks the whole S3 bucket
  2. The writer creates the next numbered JSON file in `_delta_log`; only one writer can create a given version
  3. It renames the data folder
  4. It writes to a central database row
Show the answer

The writer creates the next numbered JSON file in `_delta_log`; only one writer can create a given version — Each version is a file like 000…042.json created with put-if-absent semantics. If another writer already created v42, you re-check for conflicts and try v43.

2. In Iceberg, what is swapped atomically to commit a new snapshot?

  1. The manifest files
  2. The Parquet footers
  3. The catalog's pointer to the current metadata.json
  4. A _SUCCESS marker file
Show the answer

The catalog's pointer to the current metadata.json — Iceberg writes new data, manifests and a new metadata file, then the catalog (Glue, REST, Hive, Nessie) atomically updates the table's current-metadata pointer.

3. Which feature lets an Iceberg user write WHERE ts >= '2026-03-14' and still get partition pruning without a separate date column?

  1. Hidden partitioning with a transform like days(ts)
  2. Z-ordering
  3. Deletion vectors
  4. Hudi's record index
Show the answer

Hidden partitioning with a transform like days(ts) — The partition spec stores days(ts); Iceberg maps the filter on ts to partitions itself, so users can't forget or mistype a partition column.

4. A CDC feed applies 50,000 updates per minute to drivers. Reads are occasional. Which strategy fits best?

  1. Copy-on-write with a full table rewrite every minute
  2. Plain Parquet overwrite
  3. Time travel
  4. Merge-on-read, with compaction scheduled
Show the answer

Merge-on-read, with compaction scheduled — MoR writes small delete/log files cheaply per batch; reads merge them and compaction keeps that cost bounded. CoW would rewrite many files every minute.

5. You run VACUUM rides RETAIN 0 HOURS (after disabling the safety check). What is the consequence?

  1. Time travel to earlier versions breaks, and running readers may lose files they still need
  2. Nothing — VACUUM only compacts
  3. The table is dropped
  4. Only the log is deleted
Show the answer

Time travel to earlier versions breaks, and running readers may lose files they still need — VACUUM deletes data files no longer referenced by the current version. Zero retention removes the files old versions — and in-flight queries — depend on.

6. Your team uses Spark for ETL, Trino for ad-hoc and Snowflake for BI, all on one copy of the data. Most natural format?

  1. Hudi Merge-on-Read only
  2. Apache Iceberg
  3. CSV with a Hive metastore
  4. Delta Lake without UniForm
Show the answer

Apache Iceberg — Iceberg has the broadest native multi-engine support, including Snowflake and Trino. (Delta with UniForm can expose Iceberg metadata, but Iceberg is the direct answer.)

There are 10 questions, 3 puzzles and 5 recall cards for this lesson in the app — the recall cards come back on later days, just before you would forget.

Learn it so it stays. Read it, test yourself, then recall it on two different days. The app schedules that for you, free.

Start this lesson →