Skip to content

computer: Let several Workspaces share one durable object's storage - #246

Draft
mattzcarey wants to merge 1 commit into
mainfrom
workspace-namespaces
Draft

mattzcarey wants to merge 1 commit into
mainfrom
workspace-namespaces

Conversation

@mattzcarey

Copy link
Copy Markdown
Member

A durable object's storage can hold only one Workspace, because every table a Workspace creates has a fixed name (#219). An agent that wants a scratch area next to a durable project, or one Workspace per sub-task, needs a separate durable object for each.

WorkspaceOptions now takes a namespace:

const project = new Workspace({ storage: ctx.storage });
const scratch = new Workspace({ storage: ctx.storage, namespace: "scratch" });

A namespaced Workspace gets its own copy of every table and index, named with a ws_<namespace>_ prefix. So vfs_nodes becomes ws_scratch_vfs_nodes. Without a namespace a Workspace keeps the existing names, so stored data stays where it is.

The table names are spread across the filesystem, sync, mount and runtime code, roughly 50 files of SQL. Rather than thread a prefix through all of it, the Workspace wraps its storage handle and renames its own identifiers in the SQL on the way to SQLite. I picked this because it's the smallest change, but it's the main thing to review. The trade-offs:

  • File names and contents are never touched, because values always travel as bindings. A test writes a file called vfs_nodes.sql containing SQL and reads it back unchanged.
  • The rename matches only vfs_*, _vfs_*, workspace_runtime_* and computer_execution_runtime. A test checks that a namespaced Workspace creates no table or index outside its prefix, so a new table that the pattern misses fails the build.
  • Namespaces are 1 to 32 lowercase letters and digits. Leaving out _ means two namespaces can never map to the same table names.

A durable object still has one container. Two Workspaces with container backends in the same object would fight over it, so the README says to give a container backend to only one of them. Container-backend state such as the client secret and launch record also lives in key-value storage under fixed keys, which is one more reason to keep it to one Workspace.

The new namespace.test.ts covers:

  • files kept apart across three Workspaces on one storage
  • reopening a namespace
  • the default tables untouched, and existing data still readable
  • no rewriting of file data
  • a separate Git repository per namespace
  • namespaces that could clash being rejected

npm test --workspace @cloudflare/computer passes. The README has a new "Several workspaces in one durable object" section, docs/03_filesystem_schema.md explains the prefix, and a minor changeset is included.

A durable object's storage held exactly one Workspace, because every
table it creates has a fixed name. An agent that wanted a scratch area
next to a durable project, or one Workspace per sub-task, needed a
durable object for each.

WorkspaceOptions now takes a `namespace`. A namespaced Workspace gets
its own copy of every table and index, named with a `ws_<namespace>_`
prefix, so `vfs_nodes` becomes `ws_scratch_vfs_nodes`. Without a
namespace a Workspace keeps the existing names, so stored data stays
where it is.

The table names are spread across the filesystem, sync, mount, and
runtime code, so rather than thread a prefix through all of it, the
Workspace wraps its storage handle and renames its own identifiers in
the SQL on the way to SQLite. Values always travel as bindings, so file
names and contents are never touched. Namespaces are lowercase letters
and digits only, which keeps two namespaces from ever mapping to the
same table names. A test checks that a namespaced Workspace creates no
table or index outside its prefix, so a new table that the rename
misses fails the build.

A durable object still has one container, so only one Workspace in it
should have a container backend. The README and the schema doc say so.

Fixes #219.
@changeset-bot

changeset-bot Bot commented Oct 16, 2026

Copy link
Copy Markdown

馃 Changeset detected

Latest commit: 4487be9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@cloudflare/computer Minor
@cloudflare/dofs Minor
@cloudflare/computer-rpc Minor
@cloudflare/computerd Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Oct 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@cloudflare/computer@246

commit: 4487be9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant