Project Nessie

Project Nessie is an open-source “Git-for-data” catalog for Apache Iceberg, started by Dremio. It treats data tables the way Git treats source code — commits, branches, tags, and merges — layered on top of an Iceberg metastore. Nessie makes experimentation, isolation, and rollback first-class operations instead of one-off engineering exercises.

Below: how Nessie stores versions, the branch-validate-merge workflow, a Spark SQL example, and how it compares with other lakehouse catalogs.

1. Key Features

2. Why It Matters

Traditional lakehouse releases mix data ingestion with data publication — a partial load is visible to consumers immediately. Nessie inverts this: ingestion happens on a feature branch, validation and QA run against that branch, and only a successful merge exposes the change to the production view. The data team gets the same review-and-promote workflow software engineers have had since the late 2000s.

3. Use Cases

4. How it works

Where Nessie Sits Spark / Flink writers Trino / Dremio readers Nessie server commits, refs Version store JDBC, RocksDB... Iceberg files S3 / ADLS / GCS Nessie stores only metadata pointers per reference; table data and Iceberg metadata stay in object storage.

For an Iceberg table, the only mutable piece of state is the pointer to the table's current metadata file. An ordinary catalog stores one such pointer per table. Nessie instead stores a commit log: each commit records the set of table pointers that changed, and a branch or tag is a named reference to a commit. Because a commit can move pointers for several tables at once, a multi-table change becomes atomic. Engines talk to Nessie through its own API or the Iceberg REST catalog protocol, specifying the reference to read or write. The version store behind the server is pluggable, with backends such as JDBC databases, RocksDB for single-node use, and cloud key-value stores.

5. Branch, validate, merge

Branch, Validate, Merge main c1 c2 merge etl load tables validate Consumers on main never see the partial load; the merge publishes every table change at once.

The core workflow mirrors feature branches in Git. A job creates a branch from main, writes new snapshots of one or more tables on that branch, runs data-quality checks against the branch, and merges only if the checks pass. If they fail, the branch is dropped and consumers never saw the bad data. Merges are applied per table: if main changed a different table meanwhile, the merge succeeds; if the same table changed on both sides, Nessie reports a conflict rather than silently combining Iceberg snapshots.

6. Worked example with Spark SQL

-- Spark session configured with the Nessie catalog named "nessie"
CREATE BRANCH IF NOT EXISTS etl_2026_10_01 IN nessie FROM main;
USE REFERENCE etl_2026_10_01 IN nessie;

INSERT INTO nessie.sales.orders SELECT * FROM staging_orders;
MERGE INTO nessie.sales.customers t USING staging_customers s
  ON t.id = s.id
  WHEN MATCHED THEN UPDATE SET *
  WHEN NOT MATCHED THEN INSERT *;

-- validation query on the branch
SELECT count(*) FROM nessie.sales.orders WHERE amount < 0;

-- publish both tables atomically
MERGE BRANCH etl_2026_10_01 INTO main IN nessie;
CREATE TAG month_end_2026_09 IN nessie FROM main;

These statements come from the Nessie Spark SQL extensions, which must be added to the Spark session alongside the Iceberg extensions. The tag gives auditors and ML pipelines a stable name for the state of every table at month end.

7. When to use Nessie

CatalogDistinctive featureFits when
NessieGit-style branches, tags, multi-table commitsWrite-audit-publish pipelines, reproducible snapshots
Apache PolarisIceberg REST catalog with RBACVendor-neutral Iceberg governance
Unity CatalogGovernance across tables, files, modelsDatabricks-centred platforms
Hive Metastore / AWS GlueWidest legacy engine supportExisting Hive-era estates

8. Pitfalls

See Apache Iceberg for the table format Nessie versions, the Catalogs overview, and Trino for querying Nessie-managed tables.