⌘K ctrl+k
Search Shortcut cmd + k | ctrl + k
Iceberg Extension

The iceberg extension implements support for the Apache Iceberg open table format. There are two ways to work with Iceberg in DuckDB:

  • Individual tables are read directly from storage, by pointing at a table's metadata. This requires no catalog and is read-only.
  • Catalog-managed tables are accessed by attaching an Iceberg REST catalog. This unlocks the full feature set, including writing.

This page covers the basics of both. See also:

  • Writing to Iceberg describes the supported write operations, partitioning and schema evolution.
  • Iceberg Functions documents the functions provided by the extension.
  • Iceberg Options documents the scan parameters, ATTACH options, secret options and settings.
  • Catalogs explains how to attach an Iceberg REST Catalog, with instructions for specific catalogs.
  • Troubleshooting lists common problems and their solutions.

Installing and Loading

The iceberg extension is installed and loaded automatically on first use. If you would like to install and load it manually, run:

INSTALL iceberg;
LOAD iceberg;

Updating the Extension

The iceberg extension often receives updates between DuckDB releases. To make sure that you have the latest version, update your extensions:

UPDATE EXTENSIONS;

Reading Iceberg Tables

Individual Iceberg tables can be read directly from storage with the iceberg_scan function, without attaching to a catalog. To test the examples, download the iceberg_data.zip file and unzip it.

Querying Individual Tables

Use the iceberg_scan function to read an Iceberg table from a path:

SELECT count(*)
FROM iceberg_scan('data/iceberg/lineitem_iceberg', allow_moved_paths = true);
count_star()
51793

The allow_moved_paths option ensures that some path resolution is performed, which allows scanning Iceberg tables that are moved.

You can also directly specify the current manifest in the query, this may be resolved from the catalog prior to the query, in this example the manifest version is a UUID. To do so, navigate to the data/iceberg directory and run:

SELECT count(*)
FROM iceberg_scan('lineitem_iceberg/metadata/v1.metadata.json');
count_star()
60175

For the full list of parameters accepted by iceberg_scan, see the Iceberg Options page.

Reading from Object Stores

The iceberg extension works together with the httpfs extension or the azure extension to access Iceberg tables in object stores such as S3 or Azure Blob Storage.

SELECT count(*)
FROM iceberg_scan('s3://bucketname/lineitem_iceberg/metadata/v1.metadata.json');

Metadata and Snapshots

To inspect the manifest entries and snapshots of a table, use the iceberg_metadata and iceberg_snapshots functions. To read tables without a version-hint.text file or with non-standard metadata file names, see Selecting Metadata Versions.

Time Travel

To read a historical snapshot of a table, pass either snapshot_from_id or snapshot_from_timestamp (the two are mutually exclusive). Use iceberg_snapshots to list the available snapshots:

-- Read a specific snapshot by id
SELECT count(*)
FROM iceberg_scan('data/iceberg/lineitem_iceberg', snapshot_from_id = 7635660646343998149);

-- Read the snapshot that was current at a given time
SELECT count(*)
FROM iceberg_scan('data/iceberg/lineitem_iceberg', snapshot_from_timestamp = TIMESTAMP '2023-02-15 15:08:00');

Limitations of Direct Reads

  • A version hint or explicit version is required to read a table, unless version guessing is enabled.
  • Only gzip-compressed metadata is supported (via metadata_compression_codec = 'gzip').

Catalog Managed Tables

For full read and write access — and to use Iceberg's catalog features — attach an Iceberg REST catalog. Most catalogs authenticate with OAuth2; store the credentials in a secret and attach the catalog with ATTACH ... (TYPE iceberg, ...):

CREATE SECRET iceberg_secret (
    TYPE iceberg,
    CLIENT_ID 'admin',
    CLIENT_SECRET 'password',
    OAUTH2_SERVER_URI 'https://catalog.example.com/v1/oauth/tokens'
);

ATTACH 'warehouse' AS my_catalog (
    TYPE iceberg,
    SECRET iceberg_secret,
    ENDPOINT 'https://catalog.example.com'
);

Once attached, the catalog behaves like any other DuckDB database: reference its tables as catalog.schema.table and query or modify them with regular SQL.

SHOW ALL TABLES;

SELECT count(*) FROM my_catalog.default.events;

INSERT INTO my_catalog.default.events VALUES (1, 'click', now());

The metadata functions also work on catalog tables when passed a fully qualified name, e.g., iceberg_snapshots(my_catalog.default.events).

  • For the full set of write operations — partitioning, UPDATE, DELETE, MERGE INTO, ALTER TABLE, and table properties — see Writing to Iceberg.
  • For catalog-specific setup, see Catalogs. For the complete list of ATTACH options and secret parameters, see Iceberg Options.

Time Travel

On an attached catalog, time travel with the AT clause directly on the table:

-- Using a snapshot id
SELECT * FROM my_catalog.default.events AT (VERSION => snapshot_id);

-- Using a timestamp
SELECT * FROM my_catalog.default.events AT (TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217');

Interoperability with DuckLake

The iceberg_to_ducklake function performs a metadata-only copy of an attached Iceberg catalog into a DuckLake catalog, letting you query Iceberg tables as if they were DuckLake tables.

Pages in This Section

© 2026 DuckDB Foundation, Amsterdam NL
DuckDB Home Code of Conduct Trademark Use Blog