Skip to main content

Automerge

Merge without conflicts. A CRDT library for building local-first collaborative apps.

Overview

Automerge is a JSON-like data structure that can be modified concurrently by different users and automatically merged without conflicts. It's the backbone of local-first software.

Key Features

Automatic Merging

┌─────────────────────────────────────────────────────────────────┐
│ Automerge Merge │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Device A (offline) │
│ doc.title = "Hello" │
│ doc.items.push("apple") │
│ │
│ Device B (offline) │
│ doc.count = 42 │
│ doc.items.push("banana") │
│ │
│ After merge: │
│ { │
│ title: "Hello", ← from A │
│ count: 42, ← from B │
│ items: ["apple", "banana"] ← both preserved! │
│ } │
│ │
│ No conflicts. No data loss. Automatic. │
│ │
└─────────────────────────────────────────────────────────────────┘

Core Features

FeatureDescription
JSON-likeObjects, arrays, text, counters
Automatic mergeNo conflict resolution needed
Offline-firstWorks without network
HistoryFull change history preserved
Efficient syncOnly send changes, not full doc

Supported Types

TypeUse Case
ObjectKey-value data
ArrayOrdered lists
TextCollaborative text editing
CounterIncrement/decrement values
DateTimestamps

Usage

Basic Example

import * as Automerge from '@automerge/automerge'

// Create a document
let doc = Automerge.init()

// Make changes
doc = Automerge.change(doc, 'Add task', doc => {
doc.tasks = []
doc.tasks.push({ title: 'Buy groceries', done: false })
})

// Get changes for sync
const changes = Automerge.getChanges(oldDoc, doc)

// Apply changes from another peer
doc = Automerge.applyChanges(doc, remoteChanges)

Collaborative Text

// Create text
doc = Automerge.change(doc, doc => {
doc.content = new Automerge.Text()
doc.content.insertAt(0, 'Hello')
})

// Insert concurrently
// Device A inserts " World" at position 5
// Device B inserts "!" at position 5

// Result: "Hello World!" - both insertions preserved

Architecture

┌─────────────────────────────────────────────────────────────────┐
│ Automerge Architecture │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Application │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Automerge Document │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │ │
│ │ │ Current State│ │ Change History│ │ Actor IDs │ │ │
│ │ └──────────────┘ └──────────────┘ └────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Sync Protocol (automerge-repo) │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ WebSocket │ │ MessageChannel│ │ BroadcastChannel│ │ │
│ │ └────────────┘ └────────────┘ └────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Automerge 2.0

The latest version brings:

FeatureBenefit
Rust core10-100x faster than JS
WASM bindingsBrowser + Node.js
Compact storageEfficient binary format
automerge-repoSync, storage, networking

Use Cases

  1. Collaborative docs — Multiple users editing simultaneously
  2. Note-taking apps — Sync across devices
  3. Project management — Shared task boards
  4. Games — Multiplayer state sync
  5. Local-first apps — Offline-capable software

Comparison

FeatureAutomergeYjsPlain JSON
Auto-mergeYesYesNo
HistoryYesLimitedNo
JSON-likeYesPartialYes
Text CRDTYesYesNo
Rust coreYesNoN/A

Ecosystem

PackagePurpose
@automerge/automergeCore library
@automerge/automerge-repoSync and storage
automerge-swiftiOS/macOS
automerge-cC bindings

See Also