---
title: "Table format"
description: "A table format is a metadata layer on top of data files in a lake or object storage that defines what constitutes a table — its schema, partitioning, and file list — enabling ACID transactions, schema evolution, and time travel across multiple query engines."
canonical: "https://motherduck.com/glossary/table-format/"
related:
  - title: "Getting Started with DuckLake: A New Table Format for Your Lakehouse"
    url: "https://motherduck.com/blog/getting-started-ducklake-table-format/"
  - title: "DuckLake | MotherDuck Docs"
    url: "https://motherduck.com/docs/concepts/ducklake/"
  - title: "A Duck Walks into a Lake"
    url: "https://motherduck.com/blog/ducklake-motherduck/"
gated_asset:
  title: "DuckLake: The Lakehouse Table Format"
  url: "https://motherduck.com/lp/ducklake-lakehouse-table-format-book-full/"
---

# Table format

> A table format is a metadata layer on top of data files in a lake or object storage that defines what constitutes a table — its schema, partitioning, and file list — enabling ACID transactions, schema evolution, and time travel across multiple query engines.

## Overview
A table format sits between raw file formats (Parquet, ORC, Avro) and the query engines that read them. A file format defines how bytes are laid out inside a single file; a table format defines how many files, potentially spread across a whole directory tree, together constitute one logical, evolving table — including its current schema, partitioning scheme, and the exact set of files that make up any given version.

<glossary-callout guide="ducklake-lakehouse-table-format-book-full" />

## What a table format adds
Without a table format, a "table" on a data lake is just a directory of files, discovered by listing that directory — the approach Hive originally used. That makes concurrent writes unsafe, schema changes destructive, and there's no way to see a consistent snapshot while a write is in progress. A table format solves this with explicit metadata: a chain of files (or, in DuckLake's case, rows in a SQL database) that record every data file, its schema version, and a full history of snapshots, giving:

- **ACID transactions** — safe concurrent reads and writes
- **Schema evolution** — adding, renaming, or dropping columns without rewriting data
- **Time travel** — querying the table as of a past version
- **Partition evolution** — changing how a table is partitioned going forward without rewriting history

## The major table formats
- **Apache Iceberg** — metadata as chained JSON/Avro files; catalogs like REST, Glue, or Hive Metastore track the current pointer.
- **Delta Lake** — a JSON transaction log (`_delta_log`) alongside Parquet data.
- **Apache Hudi** — similar goals, with strong support for incremental, upsert-heavy pipelines.
- **DuckLake** — stores metadata in a transactional SQL database (DuckDB, Postgres, or SQLite) instead of files, avoiding the file-listing overhead the other formats incur as metadata grows.

## Working with table formats in DuckDB
DuckDB has extensions for the major open table formats, so the same engine can query tables regardless of which format wrote them:

```sql
LOAD iceberg;
SELECT * FROM iceberg_scan('s3://bucket/warehouse/orders');

LOAD delta;
SELECT * FROM delta_scan('s3://bucket/warehouse/customers');

ATTACH 'ducklake:metadata.ducklake' AS lake (DATA_PATH 's3://bucket/data/');
SELECT * FROM lake.events;
```