2026 deprecation migration guide
This guide walks through migrating away from the Sandbox SDK features deprecated in June 2026. These features will no longer be present in future Sandbox SDK versions after July 9, 2026.
For the announcement and rationale, refer to the deprecation changelog entry.
Update to the latest Sandbox SDK release before changing transport or session configuration. If your project uses a version earlier than 0.9.1, deploy the newer @cloudflare/sandbox package and container image before switching to RPC transport.
Search your codebase for deprecated configuration and APIs:
rg 'SANDBOX_TRANSPORT|transport:|exposePort\(|enableDefaultSession|execStream\(|readFileStream|writeFileStream'Also review any code that uses stream-specific file helpers or depends on shell state carrying across separate exec() calls.
HTTP and WebSocket transports will no longer be present in Sandbox SDK versions released after July 9, 2026. Switch to the RPC transport before that date.
To configure RPC transport for every sandbox in your Worker, set SANDBOX_TRANSPORT in your Worker's configuration:
{ "vars": { "SANDBOX_TRANSPORT": "rpc" }}[vars]SANDBOX_TRANSPORT = "rpc"To configure RPC transport for a specific sandbox, pass transport: "rpc" to getSandbox():
import { getSandbox } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "user-123", { transport: "rpc",});For more information, refer to Transport modes.
The desktop feature was removed in 0.10.2. If your application used Sandbox SDK desktop APIs for browser automation, move that browser automation to Cloudflare Browser Run.
Keep Sandbox SDK for isolated command execution, file operations, and runtime workflows that do not require a full remote browser environment.
Replace exposePort() with the tunnels API for public URLs. The tunnels API requires RPC transport.
Use quick tunnels for development, demos, and short-lived URLs. Use named tunnels for production traffic, webhook receivers, OAuth callbacks, and stable hostnames on a zone you control.
import { getSandbox } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "my-sandbox", { transport: "rpc",});
const server = await sandbox.startProcess("python -m http.server 8080");await server.waitForPort(8080);
const tunnel = await sandbox.tunnels.get(8080);return Response.json({ url: tunnel.url });If your exposePort() flow used proxyToSandbox() to inject authentication or rewrite responses, account for that behavior before moving the public URL to a tunnel.
For more information, refer to Tunnels and Expose services.
Set enableDefaultSession: false on getSandbox(). Operations without an explicit session will then run in isolation and will not inherit shell state from earlier calls.
import { getSandbox } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "user-123", { enableDefaultSession: false, transport: "rpc",});If your code expects commands like cd /workspace/app to affect later exec() calls, create an explicit session and run related commands through that session:
const buildSession = await sandbox.createSession({ id: "build", cwd: "/workspace/app",});
await buildSession.exec("npm install");await buildSession.exec("npm test");For one-off commands, pass cwd or env directly to exec() instead of relying on persisted shell state:
await sandbox.exec("npm test", { cwd: "/workspace/app", env: { NODE_ENV: "test", },});For more information, refer to Sandbox options and Sessions.
The Sandbox SDK is consolidating separate streaming APIs into the base exec(), readFile(), and writeFile() methods. Audit code that depends on stream-specific helpers and move to the base APIs where they support streaming behavior.
For command output, use exec() with streaming callbacks:
await sandbox.exec("npm install", { stream: true, onOutput: (stream, data) => { console.log(`[${stream}] ${data}`); },});For large or binary files, use the base file APIs with RPC transport. Pass a ReadableStream to writeFile(), or read a file as a stream with encoding: "none":
const request = await fetch("https://example.com/archive.tar.gz");
if (!request.body) { throw new Error("Expected archive response body");}
await sandbox.writeFile("/workspace/archive.tar.gz", request.body);
const file = await sandbox.readFile("/workspace/archive.tar.gz", { encoding: "none",});
return new Response(file.content, { headers: { "Content-Type": file.mimeType },});For more information, refer to Commands and Files.
Use this checklist before upgrading to a Sandbox SDK version released after July 9, 2026:
- RPC transport is configured with
SANDBOX_TRANSPORT=rpcortransport: "rpc". - No
websocketorhttptransport configuration remains. - No
exposePort()usage remains in the migrated path. enableDefaultSessionis set tofalse.- Stateful command workflows use
sandbox.createSession(). - One-off commands pass
cwdandenvdirectly. - Streaming file and command code uses the base APIs.
- Your Worker has been deployed and smoke-tested.
An agent skill is available to assist with the migration: SKILL.md.