DuckLake is an integrated data lake and catalog format from the DuckDB Foundation that stores table metadata in an ACID SQL database rather than in files, with data in Parquet on object storage.
DuckLake is an extension plus a catalog database: PostgreSQL, SQLite, or DuckDB itself holds all table metadata, while data stays in Parquet on local disk or object storage. A commit is a database transaction with snapshot isolation and automatic conflict retries. Maintenance is expire_snapshots, merge_adjacent_files, and rewrite_data_files, or CHECKPOINT to run everything at once.
How DuckLake answers the questions Table Formats turns on.
| How it works | |
| Catalog | Required: a SQL database (PostgreSQL, SQLite, DuckDB) |
| Update model | Small writes inlined in the catalog; Parquet otherwise |
| Partitioning | Declared per table, murmur3 buckets included; file stats prune regardless |
| Schema evolution | Column IDs: add, drop and rename without rewriting files |
| Concurrent writers | The catalog database's transactions: snapshot isolation, conflicts retried automatically |
| Indexes | Per-file zone maps in the catalog tables; no secondary indexes |
| Change feed | table_changes() between two snapshots |
| Running it | |
| Maintenance | expire_snapshots, merge_adjacent_files, rewrite_data_files: or CHECKPOINT for all |
| Connections | |
| Engine support | DuckDB reference; clients for Spark, Trino, DataFusion and pandas |
| Cross-format reads | Copy to or from Iceberg since 0.3; Iceberg v3 deletion vectors experimental |
vs DuckLake: Operational complexity: Medium · Java
vs DuckLake: Operational complexity: Medium · Java, Python, Rust, Go
vs DuckLake: Operational complexity: Medium · Java