Create a branch for an experimental write using CALL catalog.system.create_branch(table => 'db.table', name => 'experiment-1', snapshot_id => <current_snapshot_id>) or via the Iceberg Java API with table.manageSnapshots().createBranch('experiment-1').commit()
Write data to the branch by setting the write option spark.wap.branch to the branch name in SparkSQL or passing branch in write options; reads from other branches are isolated
Validate data quality on the branch with queries scoped to it using the branch time-travel syntax: SELECT * FROM db.table VERSION AS OF 'experiment-1'
Promote the branch to main by fast-forwarding: CALL catalog.system.fast_forward(table => 'db.table', branch => 'main', to => 'experiment-1') — only works if main has not advanced past the branch's base
Create a tag to pin a known-good snapshot for audit or rollback: CALL catalog.system.create_tag(table => 'db.table', name => 'v2024-01-release', snapshot_id => <snapshot_id>, max_snapshot_age_ms => 0) so the snapshot is retained even after expire_snapshots runs
Drop stale branches and tags when no longer needed: CALL catalog.system.remove_branch / remove_tag; verify retention policy on the catalog side to avoid accumulating indefinitely retained snapshots
Known gotchas
fast_forward fails if the target branch (main) has received any new snapshots since the branch diverged; you must cherry-pick or merge manually in that case
Tags with max_snapshot_age_ms set to 0 pin their snapshot permanently; expire_snapshots will not remove it, which can cause unbounded metadata growth if tags are never cleaned up
Branch and tag support requires an Iceberg catalog that stores branch/tag state (REST, Nessie, Glue v2+); the Hive metastore catalog does not support branches or tags
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp