Cross-Side Invariant and AppliedPushCursor Verification in Cloudflare Computer

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, the driver calls assertAppliedPushCursor to validate that the returned cursor covers the local push revision:

// 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:

// 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. The checkCrossSideInvariant function implements the comparison using compareChangeCursors:

// 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:

// 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.
  • The core validation logic lives in 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, 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 within the checkCrossSideInvariant function. The verification is invoked from 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 demonstrating failure scenarios.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →