Iceberg Time Travel Explained: What It Is and How It Works
Iceberg time travel lets you query any past table state using immutable snapshots. Every write creates a snapshot — a complete record of which data files were visible at that moment. Use TIMESTAMP AS OF or VERSION AS OF to query any past point, or roll back a bad write in seconds with a metadata-only rollback.
How Snapshots Work
Iceberg snapshot chain
Snapshot 1 (2026-03-20 08:00) → manifest → [file_001.parquet, file_002.parquet]
│
Snapshot 2 (2026-03-21 14:30) → manifest → [file_001.parquet, file_002.parquet,
│ file_003.parquet] ← new file
Snapshot 3 (2026-03-22 09:15) → manifest → [file_002.parquet, file_003.parquet,
│ file_004.parquet] ← file_001 deleted
current ↑
→ Query at 2026-03-20: reads file_001 + file_002 only
→ Query at 2026-03-21: reads file_001 + file_002 + file_003
→ Query now: reads file_002 + file_003 + file_004Core Concepts
Snapshot
Complete Table State
An immutable record of the table at a point in time. Each write (INSERT, UPDATE, DELETE, MERGE) creates a new snapshot. Snapshots point to manifest files, which point to data files.
Snapshot ID
Unique Version Handle
A long integer identifying each snapshot. Use with VERSION AS OF for exact version pinning. More precise than timestamp (two writes can share the same second).
Rollback
Undo a Bad Write
Setting the current snapshot to a past one — a metadata-only operation that completes in seconds. No data files are deleted; the new "current" snapshot just points to old files.
Time Travel Queries
All three methods — timestamp, snapshot ID, and branch/tag — work in Spark SQL, Trino, and PySpark. Choose the right one for your use case.
-- 1. By timestamp (Spark SQL)
SELECT * FROM catalog.db.events
TIMESTAMP AS OF '2026-03-22 00:00:00';
-- 2. By snapshot ID (exact version)
SELECT * FROM catalog.db.events
VERSION AS OF 5432109876543210987;
-- 3. PySpark: by timestamp
spark.read.option(\n 'as-of-timestamp', 1711065600000 # Unix ms
}.table('catalog.db.events')
-- 4. Rollback to a snapshot
CALL catalog.system.rollback_to_snapshot(
'db.events', 5432109876543210987
)Snapshot Lifecycle Management
| Operation | Command | When to run |
|---|---|---|
| List snapshots | SELECT * FROM table.snapshots | Debugging, find snapshot ID |
| Expire old snapshots | CALL sys.expire_snapshots('db.t', TIMESTAMP '...') | Weekly — free up storage |
| Rollback to snapshot | CALL sys.rollback_to_snapshot('db.t', id) | After bad write |
| Rollback to timestamp | CALL sys.rollback_to_timestamp('db.t', TIMESTAMP '...') | After bad deployment |
| Remove orphan files | CALL sys.remove_orphan_files('db.t') | After expire_snapshots |
Common Mistakes
Never expiring snapshots
Snapshots keep old data files alive indefinitely. A table with daily writes and no expiry accumulates years of data files even if the logical table stays small. Run expire_snapshots() weekly, keeping the last 7–30 days.
Rolling back without checking downstream
Rolling back a table also affects downstream consumers that may have already read and processed the data in the snapshots being rolled back. Coordinate rollbacks with downstream teams or use branches (Nessie) for isolated rollback testing.
Confusing snapshot expiry with data deletion
Expiring a snapshot does not delete the underlying data files unless those files are orphaned (referenced by no other live snapshot). Data shared across snapshots is preserved.
FAQ
- How does Iceberg time travel work?
- Every write creates an immutable snapshot. Query past states with TIMESTAMP AS OF or VERSION AS OF — Iceberg resolves the snapshot and returns data from the files that existed at that time.
- How do I roll back an Iceberg table to a previous snapshot?
- CALL catalog.system.rollback_to_snapshot('db.table', <snapshot_id>). Metadata-only operation, completes in seconds. Data files are not deleted.
- How long does Iceberg keep snapshots?
- Indefinitely — until you explicitly run expire_snapshots(). No automatic cleanup. Schedule weekly expiry keeping 7–30 days of history.
- What is the difference between Iceberg time travel and Delta Lake time travel?
- Same concept, different syntax. Iceberg: TIMESTAMP AS OF / VERSION AS OF. Delta: TIMESTAMP AS OF / VERSION AS OF. Delta retains 30 days by default. Iceberg retains indefinitely until you expire.