Document Versions & Time Travel
LH42 provides full document versioning and time-travel capabilities powered by Apache Iceberg's snapshot-based architecture. Every change to your documents is tracked, enabling historical queries, version comparison, and rollback.
What is Time Travel?
Time travel allows you to:
- Query historical data - Access any previous state of your documents
- Compare versions - See exactly what changed between two points in time
- Restore previous versions - Roll back to an earlier document state
- Audit compliance - Maintain complete history for regulatory requirements
How It Works
Every operation in LH42 creates an Iceberg snapshot. Each snapshot represents a complete, consistent state of your data at that moment. Snapshots are:
- Immutable - Cannot be modified after creation
- Efficient - Only store changed data (copy-on-write)
- Queryable - Access any snapshot by ID or timestamp
Document Version API
List Document Versions
Get all versions for a specific document:
GET /api/documents/{documentId}/versions?limit=50&offset=0
# Response
{
"versions": [
{
"id": "ver_abc123",
"versionNumber": 3,
"trigger": "update",
"changeSummary": "Updated pricing section",
"createdAt": "2026-01-20T10:30:00Z",
"createdBy": "user_xyz",
"snapshotId": "1234567890123456789"
},
{
"id": "ver_def456",
"versionNumber": 2,
"trigger": "update",
"changeSummary": "Added new chapter",
"createdAt": "2026-01-15T14:00:00Z",
"createdBy": "user_xyz",
"snapshotId": "1234567890123456788"
}
],
"pagination": {
"total": 12,
"limit": 50,
"offset": 0,
"hasMore": false
}
}Get Specific Version
Retrieve details for a specific version:
GET /api/documents/{documentId}/versions/{versionId}
# Response
{
"version": {
"id": "ver_abc123",
"documentId": "doc_xyz",
"versionNumber": 3,
"trigger": "update",
"changeSummary": "Updated pricing section",
"contentHash": "sha256:abc123...",
"metadata": {
"wordCount": 2500,
"chunkCount": 12
},
"createdAt": "2026-01-20T10:30:00Z",
"createdBy": "user_xyz"
}
}Compare Versions
See the differences between two versions:
GET /api/documents/{documentId}/versions/compare?from={versionId1}&to={versionId2}
# Response
{
"comparison": {
"fromVersion": {
"id": "ver_def456",
"versionNumber": 2,
"createdAt": "2026-01-15T14:00:00Z"
},
"toVersion": {
"id": "ver_abc123",
"versionNumber": 3,
"createdAt": "2026-01-20T10:30:00Z"
},
"changes": {
"contentChanged": true,
"metadataChanged": true,
"chunksAdded": 2,
"chunksRemoved": 0,
"chunksModified": 3
}
}
}Restore a Version
Roll back to a previous version (creates a new version with the restored content):
POST /api/documents/{documentId}/versions/{versionId}/restore
Content-Type: application/json
{
"changeSummary": "Restored to version 2 after incorrect update"
}
# Response
{
"success": true,
"message": "Document restored to version 2",
"version": {
"id": "ver_ghi789",
"versionNumber": 4,
"trigger": "restore",
"changeSummary": "Restored to version 2 after incorrect update",
"createdAt": "2026-01-21T09:00:00Z"
}
}Time Travel Query API
For advanced time-travel queries at the Iceberg table level:
Query Historical Data
Query data as it existed at a specific point in time:
# Query by snapshot ID
result = client.time_travel.query(
table_name="documents",
namespace="org_abc123",
snapshot_id="1234567890123456789",
columns=["id", "title", "created_at"],
limit=100
)
for row in result.rows:
print(f"{row['id']}: {row['title']}")
# Query by timestamp
result = client.time_travel.query(
table_name="chunks",
namespace="org_abc123",
as_of_timestamp="2024-01-15T10:30:00Z",
where="document_id = 'doc-123'"
)REST API equivalent:
POST /api/v1/time-travel/query
Content-Type: application/json
{
"table_name": "documents",
"namespace": "org_abc123",
"snapshot_id": "1234567890123456789",
"columns": ["id", "title", "created_at"],
"limit": 100
}List Snapshots
View available snapshots for a table:
snapshots = client.time_travel.list_snapshots(
table_name="documents",
namespace="org_abc123",
limit=10
)
for snap in snapshots.snapshots:
print(f"{snap.snapshot_id}: {snap.operation} at {snap.committed_at}")
if snap.summary:
print(f" Added records: {snap.summary.get('added-records', 'N/A')}")REST API equivalent:
GET /api/v1/time-travel/snapshots?namespace=org_abc123&table_name=documents&limit=10Compare Snapshots
Get detailed diff between two snapshots:
diff = client.time_travel.diff(
table_name="documents",
namespace="org_abc123",
from_snapshot_id="1234567890",
to_snapshot_id="1234567891"
)
print(f"Added rows: {diff.added_rows}")
print(f"Deleted rows: {diff.deleted_rows}")
print(f"Changed files: {diff.changed_files}")REST API equivalent:
POST /api/v1/time-travel/diff
Content-Type: application/json
{
"table_name": "documents",
"namespace": "org_abc123",
"from_snapshot_id": "1234567890",
"to_snapshot_id": "1234567891"
}Use Cases
Audit Trail
Maintain complete history of all document changes for compliance:
# Get full version history
versions = client.documents.list_versions(
document_id="doc_123",
limit=100
)
for v in versions:
print(f"v{v.version_number} by {v.created_by} at {v.created_at}")
print(f" Change: {v.change_summary}")Rollback After Errors
Quickly recover from accidental changes or errors:
# Find the last good version
versions = client.documents.list_versions(document_id="doc_123")
last_good = versions[1] # Previous version
# Restore it
client.documents.restore_version(
document_id="doc_123",
version_id=last_good.id,
change_summary="Rollback: Reverted erroneous update"
)Compliance & Legal Discovery
Query documents as they existed at a specific date:
# Get document state on a specific date
result = client.time_travel.query(
table_name="documents",
namespace="org_abc123",
as_of_timestamp="2025-06-15T00:00:00Z",
where="category = 'contracts'"
)Change Analysis
Understand what changed between releases or time periods:
# Compare two snapshots
diff = client.time_travel.diff(
table_name="documents",
namespace="org_abc123",
from_snapshot_id=before_release_snapshot,
to_snapshot_id=after_release_snapshot
)
print(f"Documents added: {diff.added_rows}")
print(f"Documents removed: {diff.deleted_rows}")Retention Policy
Snapshots are retained according to your plan:
| Plan | Retention |
|---|---|
| Free | 30 days |
| Pro | 1 year |
| Enterprise | Custom (up to unlimited) |
Configure retention in Settings > Data > Versioning.
Best Practices
- Add change summaries - Include descriptive summaries when updating documents
- Use meaningful timestamps - Query by timestamp for date-based compliance
- Monitor snapshot count - Large numbers of snapshots may impact query performance
- Export for long-term - Export critical snapshots before retention expiry