Skip to main content
← All Tools · 🛠️ Data Engineering & Pipeline

Apache Iceberg — Open Table Format for Huge Analytic Datasets

Apache Iceberg is an open table format for analytic datasets — ACID transactions, schema evolution, hidden partitioning, and time travel on data lakes.

Free Open source (Apache Software Foundation); managed via Snowflake, BigQuery, AWS Glue, Databricks
data-lakelakehouseparquetacidopen-table-formatdata-engineeringsparkflink

✅ Pros

  • + Hidden partitioning: query without knowing partition layout
  • + Partition evolution: change partitioning without rewriting data
  • + Multi-engine: Spark, Flink, Trino, Presto, Dremio, Snowflake, BigQuery all support it
  • + Row-level deletes and MERGE without full rewrites
  • + True open standard — no single vendor controls the spec

⚠️ Cons

  • − More complex metadata (manifest files, manifest lists) than Delta Lake
  • − REST catalog management adds operational overhead
  • − Spark write performance slightly slower than Delta Lake for some workloads
  • − Tooling ecosystem slightly less mature than Delta Lake

Overview

Apache Iceberg is the table format that Netflix built for petabyte-scale tables with thousands of concurrent readers and writers. It’s now the dominant open standard, supported natively by Snowflake, BigQuery, AWS Athena, and Databricks — making it the most portable choice for multi-cloud data lakehouses.

Core Advantages Over Plain Parquet

Hidden Partitioning: Query without specifying partition column:

-- Without Iceberg (Hive-style partitioning): you must filter by partition
SELECT * FROM orders WHERE year = 2026 AND month = 4 AND day = 2;

-- With Iceberg hidden partitioning: just filter by the natural column
SELECT * FROM orders WHERE created_at >= '2026-04-02';
-- Iceberg automatically uses the underlying day partition

Partition Evolution: Change how data is partitioned as it grows:

-- Start with monthly partitioning
ALTER TABLE orders ADD PARTITION FIELD months(created_at);

-- Switch to daily as data grows (old data keeps monthly, new data gets daily)
ALTER TABLE orders DROP PARTITION FIELD months(created_at);
ALTER TABLE orders ADD PARTITION FIELD days(created_at);

PySpark + Iceberg

spark = SparkSession.builder \
    .appName("Iceberg Example") \
    .config("spark.sql.catalog.glue_catalog", "org.apache.iceberg.spark.SparkCatalog") \
    .config("spark.sql.catalog.glue_catalog.warehouse", "s3://data-lake/iceberg/") \
    .config("spark.sql.catalog.glue_catalog.catalog-impl",
            "org.apache.iceberg.aws.glue.GlueCatalog") \
    .getOrCreate()

# Create table
spark.sql("""
    CREATE TABLE glue_catalog.analytics.orders (
        order_id        STRING,
        customer_id     STRING,
        created_at      TIMESTAMP,
        status          STRING,
        amount          DECIMAL(10,2),
        category        STRING
    )
    USING iceberg
    PARTITIONED BY (days(created_at))
""")

# Write
orders_df.writeTo("glue_catalog.analytics.orders").append()

# Merge (upsert)
spark.sql("""
    MERGE INTO glue_catalog.analytics.orders AS target
    USING new_orders AS source
    ON target.order_id = source.order_id
    WHEN MATCHED THEN UPDATE SET *
    WHEN NOT MATCHED THEN INSERT *
""")

Time Travel

-- Query historical version
SELECT * FROM orders
FOR SYSTEM_TIME AS OF TIMESTAMP '2026-04-01 00:00:00';

-- By snapshot ID
SELECT * FROM orders
FOR VERSION AS OF 8516875965979439684;

-- Show table history
SELECT * FROM orders.history;

-- Show snapshots
SELECT * FROM orders.snapshots;

Schema Evolution

-- Add column (safe, never breaks readers)
ALTER TABLE orders ADD COLUMN discount_code STRING;

-- Rename column (safe)
ALTER TABLE orders RENAME COLUMN amount TO total_amount;

-- Change type (safe promotions only, e.g., int → long)
ALTER TABLE orders ALTER COLUMN total_amount TYPE DECIMAL(12,2);

Iceberg vs Delta Lake

Apache IcebergDelta Lake
GovernanceApache FoundationLinux Foundation
Hidden partitioning✅❌
Multi-engineExcellentGood
DatabricksSupportedNative
SnowflakeNativeVia connector
BigQueryNativeNo
AWS AthenaNativeVia manifest
Best forMulti-cloud, multi-engineDatabricks-centric stacks

For Databricks-centric organizations, Delta Lake is simpler. For multi-cloud or multi-engine architectures, Iceberg’s open standard and broader engine support make it the better long-term choice.

Best For

  • Multi-engine data architectures where different teams use Spark, Trino, Flink, and Athena to query the same data — Iceberg’s open spec ensures compatibility across all engines
  • Multi-cloud organizations who need to read data from S3, GCS, and Azure Blob with a single table format that doesn’t lock them into one cloud
  • Teams adopting a lakehouse with AWS Glue, Snowflake, or BigQuery as the catalog — all natively support Iceberg as a first-class table format
  • Data mesh architectures where each domain team publishes data products as Iceberg tables consumable by any engine across the organization

Apache Iceberg vs. Delta Lake vs. Apache Hudi

Apache IcebergDelta LakeApache Hudi
Multi-engine supportExcellentGrowingPartial
Databricks nativeSupported✅ NativeSupported
AWS Athena native✅Via manifest✗
Snowflake native✅✗✗
BigQuery native✅✗✗
Streaming writes✅✅✅ (specialty)
Best forMulti-cloud, multi-engineDatabricks-centricRecord-level CDC at scale

If your stack is Databricks-only, Delta Lake is the simpler choice. Choose Iceberg for multi-engine or multi-cloud architectures where open standards and broad engine compatibility matter most.