Time Travel

Time Travel and Querying Past Snapshots

Every snapshot stays readable until it is expired, so you can query the table as it was by snapshot ID or by time. The history table lists when each snapshot became current:

time_travel.py: the orders table as of every snapshot in its historyPython
"""Time travel: the orders table as of each earlier snapshot, by ID and by timestamp."""
from lake import spark
hist = spark.sql("""SELECT h.made_current_at AS at, h.snapshot_id, s.operation,
    h.is_current_ancestor AS on_main FROM booknest.orders.history h
    JOIN booknest.orders.snapshots s USING (snapshot_id) ORDER BY at""").collect()
for h in hist:
    v = f"VERSION AS OF {h.snapshot_id}"                   # the table as of that snapshot
    n = spark.sql(f"SELECT count(*) FROM booknest.orders {v}").first()[0]
    print(f"{h.at:%H:%M:%S} {h.snapshot_id:<20} {h.operation:<8} main {h.on_main!s:<5} {n:>6}")
t = hist[0].at.strftime("%Y-%m-%d %H:%M:%S.%f")          # the moment of the first commit
n = spark.sql(f"SELECT count(*) FROM booknest.orders TIMESTAMP AS OF '{t}'").first()[0]
print(f"TIMESTAMP AS OF '{t}': {n} orders")
Output
23:48:54 698235251123635788   append   main True   66761
23:48:59 55956214015426586    append   main True  100000
23:49:24 3651595841866468341  delete   main False  99996
23:49:26 55956214015426586    append   main True  100000
23:50:24 4637335077536227122  replace  main True  100000
TIMESTAMP AS OF '2026-10-01 23:48:54.537000': 66761 orders

The history tells the story of Apache Iceberg Tables In Depth and Partition Evolution: two loads, the delete, the rollback that made the 2026 snapshot current again, and the June rewrite (replace, same rows). The rolled-back delete is off main but still readable. Trino 403,499 writes the same queries as FOR VERSION AS OF and FOR TIMESTAMP AS OF. Time travel reaches only unexpired snapshots, and expire_snapshots removes those older than five days by default, so keep what audits need with a tag.