If you want to update this page or add new content, please submit a pull request to the Homepage.
Revisions
Revisions provide version control for Yorkie documents, allowing you to save snapshots at specific points in time, browse history, and restore previous states. This guide explains how to integrate revision features into your application.
Overview
Revisions are immutable snapshots of a document's state stored on the server. Each revision contains:
- Label: A user-friendly identifier (e.g., "v1.0", "Draft", "Final")
- Description: Optional detailed explanation of what changed
- Snapshot: The complete document state in YSON format
- Timestamp: When the revision was created
- Server Sequence: The document's server sequence number at creation time
Use Cases
- Version History: Allow users to browse and restore previous document versions
- Milestone Tracking: Save important states before major changes
- Audit Trail: Maintain a record of document evolution over time
- Collaboration Review: Preview changes before accepting them
- Rollback: Recover from unwanted changes or errors
Before You Begin
This guide assumes familiarity with:
- Client and Document basics
- YSON format for understanding snapshots
How Revisions Work
When you create a revision:
- The server builds the current document state
- The state is serialized to YSON format (data only, no CRDT metadata)
- The revision is stored with metadata in the database
- A
RevisionSummaryis returned to the client
API Reference
For detailed API documentation, see JS SDK - Document Revisions.
| Method | Description |
|---|---|
client.createRevision(doc, label, description?) | Create a new revision |
client.listRevisions(doc, options?) | List revisions with pagination |
client.getRevision(doc, revisionId) | Get revision details with snapshot |
client.restoreRevision(doc, revisionId) | Restore document to a revision |
Building a Revision UI
This section shows how to build a revision management interface, using patterns from CodePair as a reference.
React Hook Pattern
Create a custom hook to manage revision state and operations:
1import { useState, useCallback, useEffect } from 'react';2import { Client, Document, RevisionSummary } from '@yorkie-js/sdk';34interface UseRevisionsOptions {5 client: Client | null;6 doc: Document<any, any> | null;7 enabled?: boolean;8}910export function useRevisions({ client, doc, enabled = true }: UseRevisionsOptions) {11 const [revisions, setRevisions] = useState<RevisionSummary[]>([]);12 const [isLoading, setIsLoading] = useState(false);13 const [error, setError] = useState<Error | null>(null);1415 // Fetch revision list16 const fetchRevisions = useCallback(async (options?: {17 pageSize?: number;18 offset?: number;19 isForward?: boolean;20 }) => {21 if (!client || !doc) return;2223 setIsLoading(true);24 setError(null);2526 try {27 const revs = await client.listRevisions(doc, {28 pageSize: options?.pageSize ?? 50,29 offset: options?.offset ?? 0,30 isForward: options?.isForward ?? false, // newest first31 });32 setRevisions(revs);33 return revs;34 } catch (err) {35 const error = err instanceof Error ? err : new Error('Failed to fetch revisions');36 setError(error);37 throw error;38 } finally {39 setIsLoading(false);40 }41 }, [client, doc]);4243 // Create a new revision44 const createRevision = useCallback(async (label: string, description?: string) => {45 if (!client || !doc) {46 throw new Error('Client or document not available');47 }4849 setIsLoading(true);50 try {51 const revision = await client.createRevision(doc, label, description);52 await fetchRevisions(); // Refresh list53 return revision;54 } catch (err) {55 const error = err instanceof Error ? err : new Error('Failed to create revision');56 setError(error);57 throw error;58 } finally {59 setIsLoading(false);60 }61 }, [client, doc, fetchRevisions]);6263 // Get revision with full snapshot64 const getRevision = useCallback(async (revisionId: string) => {65 if (!client || !doc) {66 throw new Error('Client or document not available');67 }68 return client.getRevision(doc, revisionId);69 }, [client, doc]);7071 // Restore to a previous revision72 const restoreRevision = useCallback(async (revisionId: string) => {73 if (!client || !doc) {74 throw new Error('Client or document not available');75 }7677 setIsLoading(true);78 try {79 await client.restoreRevision(doc, revisionId);80 await client.sync(); // Ensure changes propagate81 await fetchRevisions(); // Refresh list82 } catch (err) {83 const error = err instanceof Error ? err : new Error('Failed to restore revision');84 setError(error);85 throw error;86 } finally {87 setIsLoading(false);88 }89 }, [client, doc, fetchRevisions]);9091 // Load revisions on mount92 useEffect(() => {93 if (enabled && client && doc) {94 fetchRevisions();95 }96 }, [enabled, client, doc, fetchRevisions]);9798 return {99 revisions,100 isLoading,101 error,102 fetchRevisions,103 createRevision,104 getRevision,105 restoreRevision,106 };107}
Using the Hook
1function RevisionPanel() {2 const { client, doc } = useYorkie(); // Your Yorkie context3 const {4 revisions,5 isLoading,6 createRevision,7 getRevision,8 restoreRevision,9 } = useRevisions({ client, doc });1011 const handleCreate = async () => {12 const label = `v${new Date().toISOString().split('T')[0]}`;13 await createRevision(label, 'Manual checkpoint');14 };1516 const handlePreview = async (revisionId: string) => {17 const revision = await getRevision(revisionId);18 // Display revision.snapshot in a preview dialog19 };2021 const handleRestore = async (revisionId: string) => {22 if (confirm('Restore to this revision? Current state will be replaced.')) {23 await restoreRevision(revisionId);24 }25 };2627 return (28 <div>29 <button onClick={handleCreate} disabled={isLoading}>30 Save Revision31 </button>32 <ul>33 {revisions.map((rev) => (34 <li key={rev.id}>35 <span>{rev.label}</span>36 <span>{new Date(rev.createdAt).toLocaleString()}</span>37 <button onClick={() => handlePreview(rev.id)}>Preview</button>38 <button onClick={() => handleRestore(rev.id)}>Restore</button>39 </li>40 ))}41 </ul>42 </div>43 );44}
Previewing Snapshots
Use the YSON parser to convert snapshots into readable data:
1import { YSON } from '@yorkie-js/sdk';23async function previewRevision(revisionId: string) {4 const revision = await client.getRevision(doc, revisionId);56 if (revision.snapshot) {7 // Parse YSON to get document data8 const data = YSON.parse<YourDocType>(revision.snapshot);910 // For Text fields, convert to plain string11 if (data.content) {12 const plainText = YSON.textToString(data.content);13 console.log('Document content:', plainText);14 }15 }16}
Restoration Flow
When restoring a revision, the server:
- Loads the revision's YSON snapshot
- Creates a new document state from the snapshot
- Applies the change through the CRDT merge process
- Syncs the restored state to all connected clients
Restoring replaces the entire document state. Consider creating a new revision before restoring to preserve the current state as a backup.
Auto-Revisions
Yorkie can automatically create revisions during snapshot creation. This is controlled by the auto-revision-enabled project setting.
| Setting | Default | Description |
|---|---|---|
auto-revision-enabled | true | Automatically create revisions during snapshots |
When enabled:
- Revisions are created automatically during garbage collection snapshots
- Labels follow the format:
snapshot-{serverSeq} - Descriptions:
Auto created revision of snapshot #{serverSeq}
Configure via the Dashboard or Admin API. See Resources for details.
Best Practices
When to Create Revisions
- Before major edits: Save state before significant changes
- At milestones: Mark completion of features or sections
- Periodically: For long editing sessions, create time-based checkpoints
- Before restore: Always save current state before restoring an old revision
Labeling Conventions
Use consistent, descriptive labels:
| Pattern | Example | Use Case |
|---|---|---|
| Version numbers | v1.0, v2.1 | Release milestones |
| Date-based | 2024-01-15, backup-2024-01-15 | Time-based checkpoints |
| Feature names | auth-complete, refactor-done | Feature milestones |
| Descriptive | before-review, final-draft | Workflow stages |
Storage Considerations
- Revisions store full document snapshots, not deltas
- Each revision consumes storage proportional to document size
- Use auto-revisions judiciously for large documents
- Consider periodic cleanup of old revisions if storage is a concern
Permissions
Revision operations require appropriate document permissions:
| Operation | Required Permission |
|---|---|
| Create | Write access |
| List | Read access |
| Get | Read access |
| Restore | Write access |
Related Documentation
- JS SDK - Document Revisions - Complete API reference
- YSON - Understanding snapshot format
- Resources - Project configuration including auto-revisions
- CodePair - Reference implementation