DBTrail
Guides

Export to Iceberg

Hand your data to Spark, Trino, Athena or Snowflake as Apache Iceberg tables, without touching your database.

Only when something downstream requires Iceberg. For your own queries, Query in DuckDB reads the same files with no copy.

What DBTrail keeps, your snapshot and every change since, is only read and left untouched. The export writes a new copy as Iceberg tables in a folder you choose. DuckDB and Spark read those straight off the folder; Trino, Athena and Snowflake read them through a catalog.

Run it

Backups → Keep it current with Iceberg gives the line for that server, with its connection and backup location filled in. Replace the stars with the index password, pick a folder, run it from cron, CI or a timer. It never runs inside the capture daemon.

The Keep it current with Iceberg panel on the Backups page: three stages showing this server's history becoming Iceberg tables written where you point them, read straight off the folder by DuckDB and Spark or through a catalog by Trino, Athena and Snowflake; two bars for what a first run costs against every run after it; the ready-made export command with a Copy button; and a fold labelled How to run it.
bintrail export iceberg --index-dsn "..." --baseline-dir /data/baselines \
  --warehouse /data/iceberg --tables shop.orders,shop.customers

Every run after the first is small

The first run loads the whole snapshot, shown as a wide bar. The next run and the one after are thin bars: only what changed. Run it as often as you want the tables to be fresh, it picks up where it left off.

Each run reads only the changes since its last run and commits one Iceberg snapshot per table. Where it left off is stored in that commit, inside the table; nothing is written back to DBTrail.

What a run tells you

Iceberg export summary: warehouse /data/iceberg, run at 2026-08-29T10:17:00Z. shop.orders is 12,400 rows loaded from the backup plus 318 change events folded in, verdict loaded; shop.customers is 2,051 rows plus 4 events, verdict loaded.
  • Nothing new: says so, writes nothing.
  • A table it cannot advance keeps its copy, retries next run, and does not stop the others. Exit is non-zero, so your scheduler sees it.
  • A run that dies halfway leaves the last complete commit readable.

Limits

  • A second run on the same folder is refused while one holds its lock.
  • --warehouse is a local directory; no direct S3 output yet.
  • MySQL and MariaDB sources; the PostgreSQL capture binary does not have it.
  • Tables need a primary key; unsupported column types are named in the run.

Options, type mapping, reading from each engine, every refusal: repository reference.

On this page