Docs / From CRDTs

Migration Guide

Migrate from CRDTs to ATOMiK

CRDTs and ATOMiK both solve distributed convergence without coordination. This guide maps CRDT concepts to ATOMiK operations, shows before/after code for three common patterns, and provides a step-by-step migration checklist.

When to migrate (and when not to)

Migrate when:

  • Your CRDT merge is a performance bottleneck (O(n) state merges)
  • Causality metadata (vector clocks, dot stores) dominates bandwidth
  • You need undo/rollback (impossible with monotonic CRDTs)
  • Your data is numeric or binary (counters, flags, fingerprints)
  • You want machine-checked algebra properties as one technical assurance input

Stay with CRDTs when:

  • You need rich set semantics (OR-Set add/remove with tombstones)
  • Your data requires causal ordering guarantees between operations
  • You use collaborative text editing (CRDTs like Yjs/Automerge excel here)
  • Your CRDT library already meets performance requirements

Conceptual Mapping

CRDTs use a join-semilattice. ATOMiK uses an Abelian group. The algebraic structure is different, but the modeled convergence property is related -- any permutation of operations produces the same final state.

CRDTATOMiKNotes
CRDT StateAtomikContextBoth represent a convergent replicated value. ATOMiK separates reference state from accumulated deltas.
merge(a, b)ctx.accum(delta)CRDT merge is a join on the semilattice. ATOMiK accumulation is XOR in an Abelian group. Both are commutative.
CRDT PayloadDelta (XOR diff)CRDTs transmit full state or operation. ATOMiK transmits the XOR of what changed -- typically much smaller.
Causality metadataModel-dependentVector clocks, version vectors, and dot stores may not be needed inside a fit XOR model. Protocol-level causality remains workload-specific.
Conflict resolutionAlgebraic convergenceCRDTs resolve via lattice join (LWW, OR-Set, etc). ATOMiK converges via Abelian-group algebra when the state model fits; application conflicts may still need product-specific handling.
query()ctx.read()Both return current value. CRDT queries the lattice state. ATOMiK reconstructs: initial_state XOR accumulator.

Pattern 1: G-Counter / PN-Counter

CRDTs use separate increment/decrement maps per node, merged with max(). ATOMiK uses a single accumulator with self-inverse deltas.

Before: CRDT PN-Counter

# Each node maintains its own counter vector
class PNCounter:
    def __init__(self, node_id, num_nodes):
        self.p = [0] * num_nodes
        self.n = [0] * num_nodes
        self.id = node_id

    def increment(self): self.p[self.id] += 1
    def decrement(self): self.n[self.id] += 1
    def value(self): return sum(self.p) - sum(self.n)

    def merge(self, other):
        # O(n) merge per node
        for i in range(len(self.p)):
            self.p[i] = max(self.p[i], other.p[i])
            self.n[i] = max(self.n[i], other.n[i])

After: ATOMiK

from atomik_core import AtomikContext

# Single context, any node can accumulate
counter = AtomikContext()
counter.load(0)

# Any node: accumulate a delta
counter.accum(delta_value)

# Read: accumulator-model O(1), no CRDT merge
current = counter.read()

# Undo: apply same delta again
counter.accum(delta_value) # self-inverse

# Sync: send a compact delta, not full state
# No vector clock inside the accumulator.
# No O(n) CRDT merge inside this path.

Pattern 2: LWW-Register

Last-Writer-Wins registers require synchronized clocks or hybrid logical clocks. ATOMiK can remove timestamp dependency in the modeled register path -- convergence is algebraic, not temporal.

Before: LWW-Register

class LWWRegister:
    def __init__(self):
        self.value = None
        self.timestamp = 0

    def set(self, val, ts):
        if ts > self.timestamp:
            self.value = val
            self.timestamp = ts

    def merge(self, other):
        # Requires synchronized clocks!
        if other.timestamp > self.timestamp:
            self.value = other.value
            self.timestamp = other.timestamp

After: ATOMiK

from atomik_core import AtomikContext

reg = AtomikContext()
reg.load(initial_value)

# Update: compute delta from current state
delta = new_value ^ reg.read()
reg.accum(delta)

# No timestamps. No clock sync.
# Convergence is algebraic:
# all replicas accumulating the same
# deltas reach the same state.

Pattern 3: Distributed State Sync

Multi-node state synchronization using CRDTs often requires transmitting full state or operation logs with causal metadata. In a fit XOR model, ATOMiK can transmit a compact delta and converge when replicas receive the same delta set.

Before: State-based CRDT Sync

# Node A sends full state to Node B
def sync_to_peer(local_crdt, peer):
    # Serialize entire CRDT state
    payload = local_crdt.serialize()
    # Includes: values + vector clock
    # + tombstones + node metadata
    peer.send(payload) # O(state_size)

def on_receive(local_crdt, payload):
    remote = CRDT.deserialize(payload)
    local_crdt.merge(remote) # O(n) merge

After: ATOMiK Delta Sync

# Node A sends a 64-bit example delta to Node B
def sync_to_peer(ctx, peer, delta):
    peer.send(delta) # 8 bytes in this representation

def on_receive(ctx, delta):
    ctx.accum(delta) # accumulator update

# No full-state serialization in this model
# No vector clocks inside the accumulator
# No tombstone garbage collection in this model
# Application conflicts remain model-specific
# Order-independent for the same delta multiset

Performance Comparison

Where CRDTs incur per-node or per-operation overhead for causality tracking, ATOMiK uses a compact accumulator path in the model; timing and space claims should be validated against the chosen implementation and workload.

DimensionCRDTsATOMiK
Merge complexityO(n) -- depends on state sizeO(1) in the accumulator model -- one XOR for fixed-width deltas
Metadata overheadVector clocks: O(nodes), Dot stores: O(ops)No vector clock inside the XOR accumulator; protocol causality is workload-specific
Sync bandwidthFull state (state-based) or op + context (op-based)64-bit delta in current examples; validate the protocol envelope per workload
State reconstructionO(1) if materialized, O(n) if from opsO(1) in the accumulator model -- initial XOR accumulator
Undo / rollbackNot supported (lattice is monotonic)Algebraic for fit XOR deltas -- apply the same delta again
Formal guaranteesSEC (Strong Eventual Consistency)Formal proof work covers the algebra; protocol guarantees remain workload-specific
Implementation complexityHigh -- many CRDT types, each with edge casesSmall core API; integration remains workload-specific

Migration Checklist

1

Assessment

  • Inventory all CRDT types in use (G-Counter, PN-Counter, OR-Set, LWW-Register, etc.)
  • Identify which CRDTs rely on monotonic growth (ATOMiK supports non-monotonic via self-inverse)
  • Map causality metadata dependencies -- if you need causal ordering, ATOMiK alone may not suffice
  • Benchmark current merge latency and sync bandwidth as a baseline
2

Prototype

  • Install atomik-core: pip install atomik-core
  • Replace one simple CRDT (G-Counter or LWW-Register) with AtomikContext
  • Validate convergence: feed the same deltas in different orders, confirm identical read()
  • Measure bandwidth reduction: compare CRDT sync payload vs the current ATOMiK delta representation
3

Integration

  • Replace CRDT merge logic with accum() calls in your replication layer
  • Remove vector clock / dot store metadata from your wire protocol
  • Update serialization: deltas are fixed-size integers, not structured CRDT payloads
  • Implement self-inverse undo if your application needs rollback (was impossible with CRDTs)
4

Validation

  • Run convergence tests: all replicas must reach identical state regardless of delta order
  • Verify self-inverse property: double-applying any delta returns to previous state
  • Load test: confirm accumulator-path performance under representative traffic
  • Monitor bandwidth: measure actual reduction vs CRDT baseline

The algebraic difference

CRDTs form a join-semilattice: merge is commutative, associative, and idempotent, but not invertible. State can only grow. ATOMiK forms an Abelian group: merge (XOR) is commutative, associative, has an identity element, and every element is its own inverse. In a fit model this gives you algebraic undo, fixed-width accumulator state, and lower metadata pressure -- at the cost of lattice monotonicity. If your application needs monotonic convergence (e.g., grow-only sets), CRDTs remain the right choice.

Historical articles and technical notes may include exploratory examples, synthesis figures, or modeled comparisons. Treat performance, power, savings, customer, production, and deployment claims as public-safe only when they are linked to measured artifacts or explicit evidence labels. Start with the current docs or evidence-label definitions.