# How Cloudflare Computer Handles Last-Write-Wins Conflicts in Multi-Container Scenarios

> Discover how Cloudflare Computer handles last-write-wins conflicts in multi-container scenarios. Learn how the system prioritizes the latest write for seamless data synchronization.

- Repository: [Cloudflare/computer](https://github.com/cloudflare/computer)
- Tags: how-to-guide
- Published: 2026-08-08

---

**Cloudflare Computer resolves concurrent write conflicts using last-write-wins semantics at the sync level, where the last container push to reach the Durable Object silently overwrites all previous changes without merging or raising errors.**

When multiple containers in the [cloudflare/computer](https://github.com/cloudflare/computer) repository concurrently modify shared state backed by Durable Objects, the runtime must reconcile divergent histories. Understanding how **last-write-wins conflict semantics** operate in multi-container scenarios is essential for building reliable distributed workloads that avoid silent data loss.

## The Last-Write-Wins Architecture

### Sync-Level Granularity

Conflict resolution in Computer operates at the granularity of an entire sync batch rather than individual files. When a container calls `Workspace.push()`, it transmits a batch of changes to the Durable Object (DO). If multiple containers push concurrently, the DO applies each batch in the order received. The batch that arrives **last** becomes the definitive state, overwriting any earlier writes to the same paths. As documented in the sync protocol specification, this behavior mirrors a shared filesystem without locking: whichever write reaches storage last persists, and no merge logic is executed [docs/02_sync_protocol.md#L341-L353](https://github.com/cloudflare/computer/blob/main/docs/02_sync_protocol.md#L341-L353).

### Local Tree Replacement During Apply

When the DO receives an upstream entry that conflicts with local state, the runtime performs a complete replacement of the local node tree. The source code explicitly notes that this implements *"last-writer-wins conflict handling"* by removing the local node and its entire subtree, then applying the upstream entry in its place [packages/computer/src/workspace.ts#L107-L110](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts#L107-L110). This means any local children residing under a conflicting path are discarded without generating tombstones or conflict markers.

## Safety Characteristics and Limitations

### Safe Multi-Container Patterns

Last-write-wins semantics are safe and efficient when containers operate on **disjoint paths**, when there is a **single writer** per path, or when files are **write-once** (such as generated build artifacts or scaffolded configuration files). In these scenarios, the arrival order of pushes does not affect correctness because no two containers modify the same data simultaneously [docs/02_sync_protocol.md#L357-L366](https://github.com/cloudflare/computer/blob/main/docs/02_sync_protocol.md#L357-L366).

### Unsafe Patterns and Lost Updates

Concurrent read-modify-write cycles on shared state produce **lost updates** under LWW semantics. For example, if two containers independently read a counter value of `5`, increment it to `6`, and push concurrently, the DO will end with `6` rather than `7` because the second push simply overwrites the first. The protocol provides no indication that an update was lost, making LWW unsuitable for collaborative editing, shared counters, or append-only logs without external coordination [docs/02_sync_protocol.md#L374-L386](https://github.com/cloudflare/computer/blob/main/docs/02_sync_protocol.md#L374-L386).

## Practical Code Examples

The following examples demonstrate how concurrent pushes resolve in practice using the `Workspace` API.

### Concurrent Overwrite Scenario

When two containers write to the same file, the second push prevails:

```typescript
import { Workspace } from "@cloudflare/computer";

// Container A executes first
const wsA = new Workspace({ storage: ctxA.storage });
await wsA.fs.writeFile("/shared/state.txt", "version-from-A");
await wsA.push();  // Arrives at DO first

// Container B executes concurrently
const wsB = new Workspace({ storage: ctxB.storage });
await wsB.fs.writeFile("/shared/state.txt", "version-from-B");
await wsB.push();  // Arrives second and wins

// Subsequent pull on any container sees only version-from-B
const ws = new Workspace({ storage: doStorage });
await ws.pull();
const content = await ws.fs.readFile("/shared/state.txt");
console.log(content); // => "version-from-B"

```

### Safe Disjoint Paths

Writes to different paths do not interfere, making arrival order irrelevant:

```typescript
const ws = new Workspace({ storage: ctx.storage });
// These writes are independent and safe under LWW
await ws.fs.writeFile("/workspace-a/config.json", "{}");
await ws.fs.writeFile("/workspace-b/config.json", "[]");
await ws.push(); // Atomic batch containing both writes

```

### Detecting Lost Updates (Manual Verification)

Because the runtime does not throw errors on conflict, applications must verify state if consistency is critical:

```typescript
// Read current value
const before = await ws.fs.readFile("/counter.txt", "utf-8"); // "5"

// Modify locally
const next = (parseInt(before) + 1).toString();
await ws.fs.writeFile("/counter.txt", next); // Write "6"

// Push may succeed but be overwritten by another container's "6"
await ws.push();

// Verification requires re-reading after next pull
await ws.pull();
const after = await ws.fs.readFile("/counter.txt", "utf-8");
if (after !== next) {
  console.warn("Update lost due to concurrent write");
}

```

## Key Implementation Files

- [`docs/02_sync_protocol.md`](https://github.com/cloudflare/computer/blob/main/docs/02_sync_protocol.md) – Defines the last-write-wins protocol semantics and documents safe versus unsafe usage patterns.
- [`packages/computer/src/workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts) – Implements the `Workspace` façade and contains the core comment describing LWW tree replacement logic.

## Summary

- **Last-write-wins** operates at the sync batch level, not individual file granularity.
- The **last push to arrive** at the Durable Object wins; earlier pushes are silently discarded without merge attempts or error generation.
- Local children under conflicting paths are **removed without tombstones** when upstream entries arrive.
- LWW is safe for disjoint paths and write-once files, but dangerous for **read-modify-write cycles** on shared state where updates may be lost.

## Frequently Asked Questions

### Does Computer detect conflicts and raise errors?

No. The Cloudflare Computer runtime implements silent last-write-wins resolution. When conflicting pushes arrive, the system applies the latest batch and discards earlier ones without throwing exceptions, returning conflict markers, or logging warnings. Applications must implement their own concurrency controls if detection is required.

### What happens to local changes when an upstream conflict arrives?

When a `Workspace.pull()` receives an upstream entry that conflicts with local state, the runtime removes the local node and its entire subtree, then applies the upstream entry. Any local-only children under the conflicting path are permanently discarded without generating tombstones, as explicitly noted in the source [packages/computer/src/workspace.ts#L107-L110](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts#L107-L110).

### Can I implement optimistic concurrency control or custom merge logic?

The built-in sync protocol does not support conditional puts or application-defined merge functions. To implement optimistic concurrency, you must layer your own versioning metadata (such as vector clocks or timestamps) on top of file contents and handle reconciliation in application code after calling `Workspace.pull()`.

### How does last-write-wins compare to CRDTs?

Unlike Conflict-free Replicated Data Types (CRDTs), which guarantee convergence through mathematical properties that preserve all concurrent updates, Computer's LWW semantics prioritize simplicity and performance by discarding all but the last write. CRDTs are suitable for collaborative editing where no update should be lost, whereas LWW is optimized for containerized batch jobs where writers typically own disjoint dataset partitions.