NewMCP ServerView docs
Configuration

Document Versions & Time Travel

Access historical versions of documents, compare changes, and restore previous states using Iceberg's built-in versioning.

8 min readUpdated 2026-02-03

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:

bash
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:

bash
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:

bash
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):

bash
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:

python
# 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:

bash
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:

python
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:

bash
GET /api/v1/time-travel/snapshots?namespace=org_abc123&table_name=documents&limit=10

Compare Snapshots

Get detailed diff between two snapshots:

python
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:

bash
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:

python
# 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:

python
# 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:

python
# 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:

python
# 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:

PlanRetention
Free30 days
Pro1 year
EnterpriseCustom (up to unlimited)

Configure retention in Settings > Data > Versioning.

Best Practices

  1. Add change summaries - Include descriptive summaries when updating documents
  2. Use meaningful timestamps - Query by timestamp for date-based compliance
  3. Monitor snapshot count - Large numbers of snapshots may impact query performance
  4. Export for long-term - Export critical snapshots before retention expiry