# How `vfs_nodes.rev` Relates to the Sync Changes Table for Tombstones in Cloudflare Computer

> Understand how vfs_nodes_rev tracks live inodes and vfs_changes_rev records tombstones in Cloudflare Computer. Learn how this enables consistent merging of updates and deletions.

- Repository: [Cloudflare/computer](https://github.com/cloudflare/computer)
- Tags: internals
- Published: 2026-08-14

---

**`vfs_nodes.rev` tracks the latest revision for live inodes, while `vfs_changes.rev` records tombstone deletions using the same global monotonic counter, enabling the sync driver to merge live updates with historical deletions into a consistent ordered stream.**

In the Cloudflare Computer project's **distributed object filesystem (DOFS)**, revision tracking forms the backbone of reliable synchronization. The VFS maintains a single global revision counter in `vfs_meta.rev`, and understanding how this counter flows into both live node records and tombstone entries is essential for grasping how the system propagates deletions across distributed clients.

## The Global Revision Counter: `vfs_meta.rev`

Every filesystem mutation—whether `mkdir`, `writeFile`, or `rm`—increments a **global, monotonically increasing revision counter**. This counter lives in `vfs_meta.rev` and serves as the single source of chronological truth for the entire VFS.

```ts
// packages/dofs/src/rev.ts
export function incrementRev(db: Database): number {
  const row = db.one<{ v: number }>(
    "UPDATE vfs_meta SET v = v + 1 WHERE k = 'rev' RETURNING v"
  );
  return row.v;               // <- new global revision
}

```

The `incrementRev()` function in [`packages/dofs/src/rev.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/rev.ts) atomically bumps this counter and returns the new value. Every subsequent operation uses this returned revision to tag its effects.

## How `vfs_nodes.rev` Tracks Live State

When an inode is created or modified, the current global revision is **copied into `vfs_nodes.rev`** for that live record. This column answers: "What is the most recent revision at which this file or directory existed in its current form?"

```ts
await db.transactionSync(async (tx) => {
  const rev = incrementRev(tx);            // bumps global rev
  tx.run(
    "INSERT INTO vfs_nodes (inode, rev, ...) VALUES (?, ?, ...)",
    inode, rev
  );
});

```

The `vfs_nodes_by_rev` index allows efficient range queries: the sync driver scans `vfs_nodes WHERE rev > ? ORDER BY rev` to find all live updates since a client's last sync point.

## Tombstones in `vfs_changes`: Preserving Delete History

When a file is deleted, the system faces a problem: simply removing the row from `vfs_nodes` would cause sync clients to never learn of the deletion. The solution is **tombstone entries** in `vfs_changes`.

```ts
// packages/dofs/src/sync/changes.ts
await db.transactionSync(async (tx) => {
  const rev = incrementRev(tx);            // same rev is used for the tombstone
  tx.run(
    "INSERT INTO vfs_changes (rev, path, op) VALUES (?, ?, 'delete')",
    rev, "/foo.txt"
  );
  // vfs_nodes entry for /foo.txt is removed elsewhere
});

```

Key design properties of this approach:

- **`vfs_changes.rev`** uses the **same global revision** as `vfs_nodes.rev`, ensuring comparable ordering
- The tombstone survives even after the `vfs_nodes` row is purged
- Multiple operations on the same path can be coalesced by taking `MAX(rev)`

## Merging Live Updates and Tombstones in the Sync Driver

The sync driver in [`packages/dofs/src/sync/coalesce.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/coalesce.ts) **merges two revision streams** to present clients with a complete, ordered change log:

```ts
// packages/dofs/src/sync/coalesce.ts
// live updates – scan by rev
db.all("SELECT inode, rev FROM vfs_nodes WHERE rev > ? ORDER BY rev");

// tombstones – scan changes table
db.all(
  "SELECT path, MAX(rev) AS rev FROM vfs_changes WHERE rev > ? AND op = 'delete' GROUP BY path"
);

```

Because both tables use the same monotonic revision counter, the sync driver can reliably interleave these results. A tombstone's revision will **always be greater than or equal to** any preceding live mutation for the same inode, preventing race conditions where a client might "resurrect" a deleted file.

## Revision Safety Guarantees

The unified revision system provides critical guarantees for distributed synchronization:

- **Ordering**: All changes—creations, updates, deletions—are totally ordered by `rev`
- **Idempotency**: Clients can resume sync from any watermark without missing changes
- **Compaction**: Old tombstones can eventually be garbage-collected once all clients have synced past them

The sync layer reads the current watermark from `vfs_meta.rev` via [`packages/dofs/src/sync/watermarks.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/watermarks.ts), then compares against `vfs_nodes.rev` for live state and `vfs_changes.rev` for historical deletions.

## summary

- **`vfs_nodes.rev`** stores the latest revision for each **live** inode, enabling efficient incremental sync of existing files
- **`vfs_changes.rev`** stores tombstone deletions using the **same global revision counter**, ensuring deletions propagate to all clients
- Both values originate from `vfs_meta.rev` via `incrementRev()` in [`packages/dofs/src/rev.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/rev.ts)
- The sync driver merges these streams in [`packages/dofs/src/sync/coalesce.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/coalesce.ts) to present a unified, ordered change log
- Tombstone revisions are always ≥ preceding live mutations, preventing synchronization anomalies

## frequently asked questions

### What happens if two clients delete the same file simultaneously?

Both insert tombstones into `vfs_changes` with different `rev` values from sequential calls to `incrementRev()`. The sync driver coalesces these using `MAX(rev)`, and clients see the deletion at the later revision. Duplicate tombstones are harmless.

### Can `vfs_nodes.rev` ever decrease?

No. The revision counter in `vfs_meta.rev` only increments, and `vfs_nodes.rev` is set to copies of this value. Even when an inode is modified, its `rev` column is updated to a higher value, never lower.

### How does the system clean up old tombstones?

Once all connected clients have synced past a tombstone's revision (tracked via watermarks in [`packages/dofs/src/sync/watermarks.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/watermarks.ts)), the entry can be safely deleted from `vfs_changes`. The revision monotonicity ensures no client will request changes from before its acknowledged watermark.

### Why not just keep deleted rows in `vfs_nodes` with a deleted flag?

Separating tombstones into `vfs_changes` allows the live filesystem queries to remain fast and simple while keeping historical data strictly for synchronization. It also enables compaction strategies that don't require scanning mixed live/deleted tables.