Is migrating from Delta to Iceberg worth it?
Summary
- Start with what the Iceberg tables must do. If Iceberg clients only need to read the data, Delta Lake's UniForm generates Iceberg metadata for existing Delta tables, and no migration is required.
- A migration is justified when an engine must write the tables as Iceberg, when your catalog manages only Iceberg tables, or when you depend on Iceberg features such as branches and tags.
- Iceberg documents two paths. A full data migration copies data into a new table with
CREATE TABLE ... AS SELECTorINSERT, and an in-place metadata migration adds Iceberg metadata over the existing data files. - Iceberg's
snapshotDeltaLakeTableaction reuses Delta data files but has documented limits: it's built and tested with Delta Standalone 0.6.0, supports Delta tables at reader version 1 and writer version 2, and depends on the source table's files. - Before moving, map the Delta features you use, such as change data feed, liquid clustering and deletion vectors, to Iceberg equivalents, and confirm every reader supports the Iceberg format version you'll write.
Is migrating from Delta to Iceberg worth it?
It depends on what the Iceberg side has to do. When Iceberg clients only need to read the data, a migration is usually unnecessary: Delta Lake's UniForm generates Iceberg metadata so those clients read the same Parquet files, with no copy and no cutover. A migration earns its effort when an engine must write the tables as Iceberg, when your catalog manages only Iceberg tables, or when a workload depends on Iceberg-specific features. Before committing, list the data copies, pipeline changes and Delta features you'd need to map to Iceberg.
Delta Lake vs Apache Iceberg: what changes in a migration
| Capability | Delta Lake | Apache Iceberg |
|---|---|---|
| Row-level deletes | Deletion vectors, enabled with delta.enableDeletionVectors |
Position or equality delete files (v2); deletion vectors (v3 and above) |
| Reading changes | table_changes or readChangeFeed, once change data feed is on |
create_changelog_view, with start and end snapshot or timestamp options |
| Data layout | Liquid clustering with CLUSTER BY, which isn't compatible with partitioning |
Hidden partitioning; partition specs evolve through metadata changes |
| Renaming and dropping columns | Column mapping allows RENAME COLUMN and DROP COLUMNS without rewriting Parquet files |
Add, drop, rename, widen and reorder are metadata changes |
| History | Time travel with VERSION AS OF and TIMESTAMP AS OF |
Time travel with the same clauses, where VERSION AS OF also accepts a branch or tag name |
| Upgrades | Protocol upgrades are irreversible and can break older readers and writers | The format version increments when older readers wouldn't read new features correctly |
What a migration involves
Iceberg's docs describe two approaches. A full data migration copies every data file into a new Iceberg table, using CREATE TABLE ... AS SELECT, INSERT or a change data capture pipeline. The new table is fully isolated from the source, and it needs a second copy of the data. One documented catch: a Spark CTAS doesn't carry over the source table's partition spec or table properties, so declare both:
CREATE TABLE prod.db.sample
USING iceberg
PARTITIONED BY (part)
TBLPROPERTIES ('key'='value')
AS SELECT ...
An in-place metadata migration keeps the existing data files and writes Iceberg metadata on top. For Delta tables, the iceberg-delta-lake module provides snapshotDeltaLakeTable, which reads the Delta table's transactions and creates an Iceberg table with the same schema and partitioning, leaving the source unchanged:
DeltaLakeToIcebergMigrationActionsProvider.defaultActions()
.snapshotDeltaLakeTable(sourceDeltaLakeTableLocation)
.as(destTableIdentifier)
.icebergCatalog(icebergCatalog)
.tableLocation(destTableLocation)
.deltaLakeConfiguration(hadoopConf)
.execute();
Read its documented limits first. The module isn't bundled with the Spark or Flink runtimes, and it's built and tested with Delta Standalone 0.6.0 for tables with minReaderVersion 1 and minWriterVersion 2. Delta features such as column mapping and deletion vectors require higher protocol versions. The snapshot also isn't the sole owner of its data files: expire_snapshots is prohibited on it, and a DELETE on the original Delta table removes files the snapshot still reads.
How to decide
- Readers only: keep Delta and enable UniForm, which gives Iceberg clients read access from one copy of the data.
- Iceberg writers: migrate the tables those engines write. Delta Lake's docs warn that an external Iceberg writer on a UniForm table may destroy the Delta table, because it may run data cleanup that Delta is unaware of.
- Feature dependence: list the Delta features in use, then confirm the Iceberg equivalent and engine support for each.
- Reader compatibility: confirm every engine reads the Iceberg format version you plan to write.
- Cutover: move all writers to the new table before cleaning up the old one, since a snapshot depends on the source files.
How Databricks approaches Delta-to-Iceberg decisions
On Databricks you can use Iceberg clients and Iceberg tables without converting existing Delta tables. Unity Catalog managed tables support both Delta Lake and Apache Iceberg, so tables in either format live in the same catalog. On Databricks Runtime 14.3 LTS and above, Iceberg reads (UniForm) make a Delta table publish Iceberg metadata while its Parquet files stay as they are. Unity Catalog's Iceberg REST catalog then serves those tables to external Iceberg clients as read-only. Tables that external engines must write can be created as managed Iceberg tables, which those engines read and write through the same REST catalog.
FAQs
Does moving to Iceberg require rewriting the data?
Not always. A snapshot migration adds Iceberg metadata over the existing Parquet files, while CREATE TABLE ... AS SELECT or INSERT copies the data into a new, fully isolated table.
Can I keep writing to the Delta table after a snapshot migration?
Iceberg's docs note that a snapshot table isn't the sole owner of its data files, so deletes against the original table can remove files it depends on. The migration is complete once all writers move to the Iceberg table.
Does UniForm work with deletion vectors?
Delta Lake's docs state that UniForm doesn't work on tables with deletion vectors enabled. On Databricks, REORG turns off and purges them while enabling Iceberg reads, deletion vectors aren't supported for Iceberg v2 reads, and the docs note that Apache Iceberg v3 supports deletion vectors.
The information provided herein is for general informational purposes only and may not reflect the most current product capabilities or configurations.