# CloudflareContainerBackend vs WorkerShellBackend vs WorkerJavaScriptBackend: Key Differences in the Computer SDK

> Explore key differences between CloudflareContainerBackend, WorkerShellBackend, and WorkerJavaScriptBackend in the Computer SDK. Understand runtime, filesystem, startup costs, and capabilities.

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

---

**The Cloudflare Computer SDK provides three distinct execution backends—Container, Worker-Shell, and Worker-JavaScript—that differ in runtime environment, filesystem handling, startup cost, and capabilities.**

The **Container** backend spins up a full Linux container, while **Worker-Shell** runs a bash interpreter inside a Dynamic Worker, and **Worker-JavaScript** executes JS modules directly in the Worker isolate. Each backend is optimized for different workloads, from heavy native builds to fast text processing to structured JavaScript execution.

## Runtime Environment Comparison

The fundamental distinction between these three backends lies in where and how your code executes.

### Container Backend: Full Linux Container

The **ContainerBackend** creates a real Linux container that runs the `computerd` daemon. This provides a complete POSIX userland including `bash`, coreutils, arbitrary binaries, and network access.

In [`packages/computer/src/backends/container/index.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/container/index.ts), the backend wires the container daemon and defines a `BackendHandle` with `sync: "remote"`【📄】. This means the container maintains its own filesystem that must be synchronized with the host Durable Object.

### Worker-Shell Backend: Bash in a Dynamic Worker

The **WorkerShellBackend** executes a **just-bash** interpreter inside a Cloudflare **Dynamic Worker**. No container is started. Instead, the shell forwards every filesystem call back to the host Durable Object.

According to the source code in [`packages/computer/src/backends/worker-shell/entrypoint.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-shell/entrypoint.ts), this backend creates a Dynamic Worker running **just-bash**, registers built-in `git` and `assets` commands, and sets `sync: "none"`【📄】.

### Worker-JavaScript Backend: Native JS Execution

The **WorkerJavaScriptBackend** runs JavaScript modules directly inside the Worker isolate. Unlike the shell backend, code is evaluated as a JavaScript module rather than a shell script, giving you a native-JS execution environment.

The implementation in [`packages/computer/src/backends/worker-javascript/module-graph.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-javascript/module-graph.ts) builds the module graph for JavaScript execution, marks the backend as *callable*, and also uses `sync: "none"`【📄】.

## Filesystem and Sync Models

| Backend | Filesystem Handling | Sync Mode |
|---------|---------------------|-----------|
| **ContainerBackend** | Separate FUSE-backed SQLite VFS inside the container; remote push/pull to host DO | `"remote"` |
| **WorkerShellBackend** | All operations proxied to host DO's SQLite store; single authoritative source | `"none"` |
| **WorkerJavaScriptBackend** | File I/O proxied to host DO's SQLite store; same storage shape as shell backend | `"none"` |

The **Container** backend's **remote** sync mode requires explicit push/pull cycles to synchronize the container's VFS with the host Durable Object. Both Worker backends eliminate this overhead by treating the host DO as the sole source of truth.

## Startup Cost and Scaling Characteristics

**ContainerBackend** incurs significant per-session overhead:

- Container creation takes seconds
- Per-session container charges apply
- Best for long-running or compute-intensive tasks

**WorkerShellBackend** offers instant, cheap scaling:

- Dynamic Worker cached per workspace (`workspace-shell:${workspace.id}`)
- Zero cold start for cached workspaces
- Ideal for high-frequency, short-duration operations

**WorkerJavaScriptBackend** shares the same scaling properties as Worker-Shell since both run in the Worker isolate without container overhead.

## Capabilities and Command Sets

### Container Backend Capabilities

Full Linux toolchain access:

- Run `npm install`, `yarn`, `pnpm`
- Compile native binaries with `gcc`, `clang`, `go`
- Invoke any binary on `$PATH`
- Network access for fetching dependencies

### Worker-Shell Backend Capabilities

Limited to **just-bash** implemented commands:

- Text utilities: `cat`, `grep`, `awk`, `sed`, `sort`, `uniq`, `wc`
- Data processing: `jq`, `head`, `tail`, `cut`
- Custom commands: `git`, `assets` (proxied to host DO)

### Worker-JavaScript Backend Capabilities

Structured JavaScript execution:

- Execute arbitrary JS modules with ES imports
- Receive structured `input` values
- Return structured `result` objects
- No shell command parsing required

## Typical Use Cases

Choose the backend that matches your workload:

- **ContainerBackend** — Heavy-weight workloads requiring a real Linux environment: building npm packages, running native binaries, complex build tools, isolated OS environments.

- **WorkerShellBackend** — Textual processing, search, transformation, or summarization using shell utilities; scenarios demanding fast startup, cheap scaling, and isolation without container overhead.

- **WorkerJavaScriptBackend** — Agent logic best expressed as JavaScript modules; custom business logic requiring library code; situations needing a *callable* backend that returns structured data rather than parsing stdout.

## Code Examples

### Container Backend

```typescript
import { ContainerBackend } from "@cloudflare/computer/backends/container";

const workspace = new Workspace({
  storage: ctx.storage,
  backends: [
    new ContainerBackend({
      // optional: custom loader, env vars, etc.
    })
  ]
});
await workspace.runtime.exec("npm install", { cwd: "/project" });

```

### Worker-Shell Backend

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

const workspace = new Workspace({
  storage: ctx.storage,
  backends: [
    new WorkerShellBackend({
      loader: env.LOADER,
      workspace: { binding: "Example", id: ctx.id.toString() },
      ctx,
    })
  ]
});
await workspace.runtime.exec("grep -R 'TODO' src/", { backend: "worker-shell" });

```

### Worker-JavaScript Backend

```typescript
import { WorkerJavaScriptBackend } from "@cloudflare/computer/backends/worker-javascript";

const workspace = new Workspace({
  storage: ctx.storage,
  backends: [
    new WorkerJavaScriptBackend({
      loader: env.LOADER,
      // `callable: true` lets you pass/receive JSON values
    })
  ]
});

const { result } = await workspace.runtime.exec({
  source: `
    export default async function (input) {
      return { hello: "world", sum: input.a + input.b };
    }
  `,
  input: { a: 3, b: 5 },
  callable: true,
  backend: "worker-javascript"
});
console.log(result); // → { hello: "world", sum: 8 }

```

## Summary

- **ContainerBackend** provides full Linux isolation with `sync: "remote"` and per-session container overhead—ideal for native builds and complex toolchains.

- **WorkerShellBackend** delivers instant-starting bash execution with `sync: "none"` and proxied filesystem access—perfect for text processing at scale.

- **WorkerJavaScriptBackend** enables structured JS module execution with `sync: "none"` and callable interfaces—best for programmatic logic requiring typed inputs and outputs.

All three backends share the same `Workspace` abstraction and SQLite-backed storage, letting you mix backends within a single application based on task requirements.

## Frequently Asked Questions

### When should I choose ContainerBackend over the Worker backends?

**ContainerBackend** is the right choice when you need actual Linux capabilities: compiling native code, running binaries not available in a restricted environment, or using tools like Docker or complex build systems. The seconds-long startup and per-session cost are acceptable tradeoffs for these workloads. According to the Cloudflare Computer source code, this backend is implemented in [`packages/computer/src/backends/container/index.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/container/index.ts) with `sync: "remote"` requiring explicit VFS synchronization【📄】.

### Can I use npm packages with WorkerShellBackend?

No. **WorkerShellBackend** only exposes commands implemented by **just-bash** plus the custom `git` and `assets` commands. It cannot run `npm`, `node`, or install JavaScript dependencies. For npm-based workflows, you must use **ContainerBackend** or pre-bundle dependencies and execute them via **WorkerJavaScriptBackend**.

### How does WorkerJavaScriptBackend handle module imports?

The backend builds a module graph in [`packages/computer/src/backends/worker-javascript/module-graph.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-javascript/module-graph.ts)【📄】. You can use standard ES module import syntax within your source string, and the loader resolves dependencies. The executed module receives a structured `input` object and must export a default function returning the structured `result`.

### Do all backends share the same storage?

Yes. All three backends ultimately persist data to the same host Durable Object's SQLite store. The difference is **how** they access it: ContainerBackend maintains a separate VFS that syncs remotely, while both Worker backends proxy I/O directly with `sync: "none"` and no intermediate filesystem layer.