# Configuring Multiple Backends for a Single Workspace in Cloudflare Computer

> Easily configure multiple backends for a single Cloudflare Computer workspace. Learn how to pass backends and default backend identifiers to createWorkspace() and route commands with exec() for efficient backend management.

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

---

**To configure multiple backends for a single Workspace in Cloudflare Computer, pass a `backends` map and a `defaultBackend` identifier to `createWorkspace()`, then route commands to specific backends using the `backend` option in `exec()` calls.**

The cloudflare/computer repository enables heterogeneous execution environments through a pluggable backend system. Configuring multiple backends for a single Workspace in Cloudflare Computer allows you to execute commands across Linux containers, bash shells, and JavaScript workers while maintaining a unified filesystem context. The runtime manages each backend through stable string IDs and ensures complete sync isolation between execution environments.

## Backend Architecture Overview

A Workspace maintains a **backends map** (`{ [id]: BackendInfo }`) and a **defaultBackend** string that determines fallback behavior. When `createWorkspace()` initializes the runtime, it stores this configuration to enable dynamic backend selection during command execution.

### The Backends Map Structure

Each entry in the backends map requires:
- A **unique ID** (string key) used for routing
- A **description** for user-facing tool definitions
- An **exec implementation** that satisfies the `Backend` interface

### Default Backend Resolution

When callers invoke `workspace.runtime.exec()` without specifying a backend, the system automatically selects the `defaultBackend` ID. This value is validated at configuration time to ensure it exists within the backends map.

## Configuration Implementation

Define your backends and create the Workspace with explicit routing configuration:

```typescript
import { createWorkspace } from "@cloudflare/computer";
import { ContainerBackend } from "./backends/container";
import { WorkerShellBackend } from "./backends/worker-shell";

/* 1️⃣  Define the backends you want to expose */
const backends = {
  // A full Linux container that mounts the workspace via FUSE
  container: {
    description: "Linux container (real FUSE mount)",
    // The concrete implementation that knows how to exec inside the container
    exec: ContainerBackend,
  },

  // A just‑bash shell that runs inside a Dynamic Worker
  shell: {
    description: "just‑bash shell (Dynamic Worker)",
    exec: WorkerShellBackend,
  },

  // Add more backends here – e.g. a JavaScript worker, a custom RPC, etc.
};

/* 2️⃣  Create the workspace, telling it which backend is the default */
const workspace = await createWorkspace({
  backends,
  defaultBackend: "container", // ← will be used when `backend` is omitted
});

/* 3️⃣  Use the runtime – callers can now pick a backend explicitly */
await workspace.runtime.exec("npm test", { backend: "shell" });
await workspace.runtime.exec("node build.js", { backend: "container" });

```

## Execution Flow and Routing

The **ExecTool** in [`packages/computer/src/tools/exec.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/tools/exec.ts) manages backend selection and validation. When processing an execution request, it extracts the backend ID using the logic `backend ?? defaultBackend`, verifies that the ID exists in the backends map, and validates callable status through `workspace.runtime.isCallable`.

**Callable backends** (such as the JavaScript worker in [`packages/computer/src/backends/worker-javascript/worker-javascript.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-javascript/worker-javascript.ts)) can receive structured `input` payloads and return `result` objects, while shell-only backends execute raw commands. The ExecTool warns if a non-callable backend receives an input payload, preventing type mismatches at runtime.

## Per-Backend Sync Isolation

Each backend maintains independent sync cursors through the **DOFS** package. In [`packages/dofs/src/sync/watermarks.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/watermarks.ts), the system keys all sync state—including watermarks and fetch cursors—by a composite tuple of `(key, backend)`.

The implementation adds a `backend` column to both the `_vfs_watermark` and `_vfs_fetch_cursor` tables, ensuring that filesystem synchronization progresses independently for each execution environment. The **sync driver** ([`packages/rpc/src/sync-driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/rpc/src/sync-driver.ts)) propagates the backend identifier down to this storage layer, preventing state interference when running multiple backends concurrently against the same workspace.

## Backend Implementation References

The repository provides several reference implementations demonstrating the Backend interface:

- **Container Backend**: [`packages/computer/src/backends/container/index.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/container/index.ts) implements full Linux containerization with FUSE filesystem mounting
- **Worker Shell Backend**: [`packages/computer/src/backends/worker-shell/worker-shell.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-shell/worker-shell.ts) provides a bash environment inside a Dynamic Worker
- **JavaScript Worker Backend**: [`packages/computer/src/backends/worker-javascript/worker-javascript.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-javascript/worker-javascript.ts) demonstrates callable backend patterns for structured computation

## Summary

- **Configure multiple backends** by passing a `backends` object and `defaultBackend` string to `createWorkspace()` according to the cloudflare/computer source code
- **Route execution** to specific backends using the `backend` option in `workspace.runtime.exec()`, or rely on the default when omitted
- **Maintain sync isolation** through per-backend cursor management in [`packages/dofs/src/sync/watermarks.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/watermarks.ts), where watermarks are keyed by `(key, backend)` tuples
- **Validate callable status** via `ExecTool` logic in [`packages/computer/src/tools/exec.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/tools/exec.ts) to ensure structured inputs only reach backends supporting module execution

## Frequently Asked Questions

### What is a backend in Cloudflare Computer?

A backend is an execution environment implementation that satisfies the `Backend` interface, such as a Linux container with FUSE mounting or a Dynamic Worker running bash. Each backend exposes an `exec` method that the Workspace runtime invokes to run commands or modules within that specific environment.

### How does sync isolation work between backends?

The DOFS layer stores synchronization metadata in tables keyed by both resource key and backend ID. Specifically, [`packages/dofs/src/sync/watermarks.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/sync/watermarks.ts) adds a `backend` column to the `_vfs_watermark` and `_vfs_fetch_cursor` tables, ensuring each backend maintains independent fetch cursors and watermarks even when accessing the same filesystem paths.

### Can I add custom backends beyond containers and shells?

Yes. You can implement any backend that satisfies the Backend interface by providing an object with a unique ID, description, and exec implementation. The [`packages/computer/src/backends/worker-javascript/worker-javascript.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-javascript/worker-javascript.ts) file demonstrates how to implement callable backends that process structured input, allowing integration of custom RPC services or specialized compute environments.

### What happens if I request a non-existent backend?

The `ExecTool` in [`packages/computer/src/tools/exec.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/tools/exec.ts) validates that the requested backend ID exists within the configured backends map before execution. If you specify a backend ID not present in the configuration, the tool rejects the request with a validation error, preventing routing to undefined execution environments.