# Cross-Side Invariant and AppliedPushCursor Verification in Cloudflare Computer

> Understand the cross-side invariant and AppliedPushCursor verification in Cloudflare Computer. Ensure Durable Objects and clients agree on applied revisions for robust data synchronization.

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

---

**The cross-side invariant ensures that the Durable Object and client agree on which revisions have been applied by verifying that the remote's `appliedPushCursor` is never behind the client's `pushCursor`.**

The Cloudflare Computer sync protocol relies on this critical safety mechanism to maintain consistency between the client and the Durable Object container. This invariant governs the relationship between the client's push cursor and the remote's applied push cursor, preventing silent divergence during data synchronization. Understanding how appliedPushCursor verification works is essential for debugging sync failures and ensuring reliable state management in distributed applications.

## What Is the Cross-Side Invariant?

The cross-side invariant is a fundamental guarantee in the Cloudflare Computer synchronization protocol that ensures both parties—the client side and the Durable Object "container" side—maintain identical views of which changes have been successfully processed.

When a client pushes a batch of changes, it records a **push cursor** (`pushCursor`) representing the highest revision (`rev`) it has transmitted. The remote side responds with an **applied push cursor** (`appliedPushCursor`), indicating the highest revision it has successfully committed. The invariant requires that:

```

compareChangeCursors(appliedPushCursor, pushCursor) >= 0

```

If the remote reports an `appliedPushCursor` that is behind the client's `pushCursor`, the system detects a violation and aborts the sync operation with a "cross-side invariant violated" error.

## AppliedPushCursor Verification in Practice

The verification of this invariant occurs during both push and pull operations to ensure continuous consistency across the network boundary.

### Push Verification

After the client sends changes via `pushOnce`, it examines the RPC response to confirm the remote has processed the sent revisions. In [`packages/rpc/src/sync-driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/rpc/src/sync-driver.ts), the driver calls `assertAppliedPushCursor` to validate that the returned cursor covers the local push revision:

```typescript
// After the RPC push response arrives, we verify the cursor.
const { appliedPushCursor } = response;
assertAppliedPushCursor(
  appliedPushCursor,
  { rev: localPushRev, path: null }   // Expected to be at least this rev
);

```

### Pull Verification

During pull operations, when `pullOnce` receives the `fetchChanges` envelope, it performs a similar check. The envelope contains an `appliedPushCursor` that must not roll back previously acknowledged revisions:

```typescript
// The fetchChanges envelope includes an appliedPushCursor.
const { appliedPushCursor, currentCursor } = fetchResult;

// Ensure the remote did not roll back our previously pushed rev.
assertAppliedPushCursor(appliedPushCursor, localPushCursor);

```

## Core Implementation in the Sync Layer

The actual comparison logic resides in [`packages/dofs/src/sync/invariant.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/invariant.ts). The `checkCrossSideInvariant` function implements the comparison using `compareChangeCursors`:

```typescript
// The invariant is enforced whenever we compare the remote's cursor
// with the local push cursor.
export function checkCrossSideInvariant(
  appliedPushCursor: ChangeCursor,
  pushCursor: ChangeCursor
) {
  // If the remote's cursor is *behind* our push cursor, abort.
  if (compareChangeCursors(appliedPushCursor, pushCursor) < 0) {
    throw new Error(
      `cross-side invariant violated: appliedPushCursor (${JSON.stringify(
        appliedPushCursor
      )}) < pushCursor (${JSON.stringify(pushCursor)})`
    );
  }
}

```

This function throws immediately when the invariant is breached, preventing the client from proceeding with an inconsistent view of the shared state.

## Recovery and Error Handling

When the cross-side invariant check fails, the sync driver handles the violation according to the operation context. The system may retry by resetting the local push revision or terminate the operation with an explicit error.

In test scenarios, the driver rejects with the invariant violation message:

```typescript
// Example from sync-driver.test.ts – retry on invariant breach
await expect(pullOnce(local, remote.rpc)).rejects.toThrow(
  /cross-side invariant violated/i
);

```

This aggressive failure mode ensures that split-brain scenarios or rollback conditions are detected immediately rather than allowing data corruption to propagate silently.

## Summary

- The **cross-side invariant** guarantees that the Durable Object has applied at least all revisions the client has pushed, verified by comparing cursors with `compareChangeCursors`.
- **AppliedPushCursor verification** occurs in both `pushOnce` and `pullOnce` operations within [`packages/rpc/src/sync-driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/rpc/src/sync-driver.ts).
- The core validation logic lives in [`packages/dofs/src/sync/invariant.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/invariant.ts), which throws "cross-side invariant violated" when the remote cursor lags behind the local push cursor.
- Violations trigger immediate sync failures or retries, ensuring the client and container never diverge silently on change history.

## Frequently Asked Questions

### What triggers a cross-side invariant violation?

A violation occurs when the remote Durable Object reports an `appliedPushCursor` that is less than the client's `pushCursor`, indicating that changes the client believes were sent have not been processed or have been rolled back. This typically happens during network partitions, server failures, or concurrent modification conflicts that result in state divergence.

### How does the sync driver recover from invariant violations?

According to the implementation in [`packages/rpc/src/sync-driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/rpc/src/sync-driver.ts), the driver may retry the synchronization by resetting the local push revision to re-establish a consistent baseline. If retry attempts fail, the operation throws an error containing "cross-side invariant violated", forcing the application layer to handle the consistency breach explicitly.

### What is the relationship between pushCursor and appliedPushCursor?

The `pushCursor` represents the highest revision the client has transmitted to the remote, while `appliedPushCursor` represents the highest revision the remote has confirmed as committed. The cross-side invariant requires that `appliedPushCursor` always be greater than or equal to `pushCursor`, ensuring the remote never appears to "forget" changes the client has already sent.

### Where is the cross-side invariant check implemented in the codebase?

The primary implementation resides in [`packages/dofs/src/sync/invariant.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/invariant.ts) within the `checkCrossSideInvariant` function. The verification is invoked from [`packages/rpc/src/sync-driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/rpc/src/sync-driver.ts) during both push and pull RPC operations, with additional test coverage in [`packages/rpc/src/sync-driver.test.ts`](https://github.com/cloudflare/computer/blob/main/packages/rpc/src/sync-driver.test.ts) demonstrating failure scenarios.