Guide

How Do You Migrate a Cloudflare Sandbox App to the @next SDK Without Breaking Production?

AI

AI Agent Skills

9 min

The Problem: You Have a Working Cloudflare Sandbox App, but the Ground Is Shifting

You built an application on Cloudflare's Sandbox platform. It works. Your team uses it daily. Then you hear that the stable @cloudflare/sandbox SDK is heading toward a major version change—Sandbox SDK 1.0—and a preview is already available as @cloudflare/sandbox@next.

The immediate reaction might be to ignore it until it becomes stable. But there's a catch: the migration isn't a simple version bump. The new SDK changes fundamental APIs, removes concepts like sessions and transport layers, and alters how processes are executed and observed. If you wait until the last minute, you'll be forced into a rushed migration under pressure.

The real pain isn't the migration itself—it's the uncertainty. What exactly changed? Which of your existing patterns will break? How do you avoid a production outage during the cutover? And how do you validate that everything still works without spending weeks reading documentation?

This is where having a structured, opinionated migration workflow becomes valuable. Not a generic guide, but a skill that knows the specific replacement patterns, the hard rules you can't violate, and the exact sequence of steps to follow.

Why This Migration Is More Than a Version Bump

The Cloudflare Sandbox SDK 1.0 preview (@next) isn't backward compatible. It's a redesign. Here's what that means in practice:

  • Sessions are gone. The stable SDK uses sessions to manage state, environments, and terminals. The @next SDK removes them entirely. You configure cwd and env per process launch instead.
  • Transport layers are removed. The stable SDK has SANDBOX_TRANSPORT, setTransport, and related configuration. The @next SDK uses RPC only—no transport abstraction.
  • Process execution changes shape. await sandbox.exec("npm test") in stable returns a buffered result. In @next, it returns a process handle, and you must explicitly call .output() to get the result.
  • Terminals work differently. The stable sandbox.terminal(request) pattern is replaced by createTerminal + terminal.connect(request).
  • Git operations are manual. The stable SDK has a gitCheckout helper. The @next SDK expects you to call git via exec with argv.
  • Kill signals are numeric only. No more string-based signal names.

These aren't edge cases—they're core API changes that affect almost every Sandbox app. If your codebase uses any of these patterns, a naive npm install @cloudflare/sandbox@next will break immediately.

What a Good Migration Solution Should Do

A useful migration tool or skill should:

  1. Audit your codebase for all patterns that need to change, not just the obvious ones.
  2. Provide a clear replacement map so you know exactly what each stable API becomes in @next.
  3. Enforce hard rules that, if violated, will cause production failures (like mixing a @next Worker with a stable container image).
  4. Guide the cutover sequence so you don't accidentally deploy an incompatible Worker and image combination.
  5. Include validation steps to confirm the migration worked before you consider it done.
  6. Know when to stop and ask for human input—especially around production cutover timing and self-deployed bridges.

Introducing the sandbox-migrate-to-next Skill

The sandbox-migrate-to-next skill is a structured workflow designed specifically for this migration. It's not a general-purpose Cloudflare tool—it's focused on one task: porting an existing app from stable @cloudflare/sandbox to @cloudflare/sandbox@next.

Here's what it does and doesn't do:

It's designed for:

  • Existing Cloudflare Sandbox apps currently on the stable SDK
  • Teams preparing for the eventual 1.0 stable release
  • Migrations where you need to preserve existing functionality

It's not designed for:

  • New projects (use sandbox-next skill instead)
  • Day-to-day development on the stable SDK (use sandbox-stable skill)
  • Cleaning up deprecated APIs without moving to @next (use the 2026 deprecation guide)

How the Migration Workflow Works

The skill follows a five-step process, with built-in checkpoints where it stops and asks for your input.

Step 1: Review Hard Rules and the Replacement Map

Before touching any code, the skill establishes the non-negotiable rules:

  • The Worker package and container image must be on the same @next line. Mixing versions will break your app.
  • Production cutover requires --containers-rollout=immediate. Gradual rollout creates an incompatible mixed window where stable and @next control protocols conflict.
  • After cutover, await sandbox.exec(...) means the process started, not that it finished. This is a fundamental behavioral change.
  • Process handles have no stdin. You can't pipe interactive input into a running process.
  • There's no universal retry loop for errors. Different errors (unavailable, interrupted RPC, stale handle, local wait timeout) need different handling.

The skill also provides a complete replacement map:

Stable Pattern @next Equivalent
SANDBOX_TRANSPORT / transport / setTransport Remove entirely—RPC only
await sandbox.exec("cmd") → buffered result await sandbox.exec(argv) → handle, then .output()
execStream / startProcess Same handle: .logs, .waitFor*, .kill
Default / named sessions Gone—use cwd/env per launch
sandbox.terminal(request) createTerminal + terminal.connect(request)
gitCheckout Call git via exec with argv
String kill signals Numeric only

Step 2: Audit the Codebase

The skill runs targeted searches to find every pattern that needs to change:

rg 'SANDBOX_TRANSPORT|transport:|setTransport|enableDefaultSession|createSession|getSession|deleteSession|execStream\(|startProcess\(|killProcess\(|sandbox\.terminal\(|sessionId|gitCheckout\(|SandboxTransport|ExecutionSession'

It also looks for subtler patterns: string-based exec( calls, cd followed by later exec calls (which won't persist state), and bare createCodeContext / runCode usage on Sandbox.

Step 3: Clarify with the User

This is where the skill stops and asks. It needs your input on:

  • Production cutover timing. Are you okay with --containers-rollout=immediate? Live processes, terminals, and streams will stop during the rollout.
  • Self-deployed bridge. If you have one, it stays on stable. The bridge isn't part of the preview line yet.
  • Python interpreter. If your app uses Python, you need the -python image variant (cloudflare/sandbox:next-python).
  • Unclear call sites. Any code that doesn't map cleanly to the replacement table needs human judgment.

Step 4: Upgrade Package, Image, and Code

The skill applies changes in order:

Package and image:

npm install @cloudflare/sandbox@next
FROM cloudflare/sandbox:next

Code changes by area:

For commands, the shape changes from a single string to an argv array:

// Before (stable)
const result = await sandbox.exec("npm test");

// After (@next)
const process = await sandbox.exec(["/bin/bash", "-lc", "npm test"]);
const result = await process.output({ encoding: "utf8" });

For long-running processes:

const server = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
  cwd: "/workspace/app",
});
await server.waitForPort(3000, { timeout: 60_000 });
await server.kill(); // numeric; default 15

For terminals:

const terminal = await sandbox.createTerminal({ command: ["bash"], cwd: "/workspace" });
const t = await sandbox.getTerminal(terminal.id);
if (!t) return new Response("terminal gone", { status: 410 });
return t.connect(request, { cursor, cols, rows });

For the interpreter:

import { Sandbox as BaseSandbox } from "@cloudflare/sandbox";
import { withInterpreter } from "@cloudflare/sandbox/interpreter";

export class Sandbox extends BaseSandbox<Env> {
  interpreter = withInterpreter(this);
}

For git operations:

const clone = await sandbox.exec(
  ["git", "clone", "--depth", "1", "--", repoUrl, "/workspace/repo"],
  { cwd: "/workspace" },
);
const result = await clone.output({ encoding: "utf8" });

The skill also tells you to delete all transport settings, remove session APIs, and isolate users with separate sandbox IDs.

Step 5: Validate

The skill runs through a validation checklist:

  1. Lockfile and Dockerfile are on the same @next line
  2. Typecheck passes against @next types
  3. Smoke test: argv exec + output({ encoding: "utf8" }) works
  4. Smoke test: long-running process, terminal, and interpreter (if used)
  5. Error handling distinguishes between unavailable, interrupted-RPC, stale, and local wait errors
  6. No live secrets in sandbox environment
  7. Grep confirms all removed APIs are gone
  8. Production deploy used --containers-rollout=immediate

When to Use This Skill (and When Not To)

Use it when:

  • You have an existing Cloudflare Sandbox app on the stable SDK
  • You want to prepare for the 1.0 stable release
  • You need a structured migration path with safety checks

Don't use it when:

  • You're starting a new project (use sandbox-next instead)
  • You're doing daily development on the stable SDK (use sandbox-stable instead)
  • You want to clean up deprecated APIs without moving to @next

What to Inspect Before Using This Skill

Before you run this migration, check:

  • Repository signals. The skill comes from Cloudflare's official skills repository (2.6k+ stars, Apache-2.0 license). It's maintained by the platform team.
  • Security level. Rated as Medium. The migration involves package changes, Dockerfile modifications, and production deployment commands. Review the changes before applying them.
  • Documentation depth. The skill references specific Cloudflare documentation pages for each area (processes, terminals, interpreter, errors, lifecycle). It fetches these when a step needs detail rather than relying on memory.
  • Your codebase complexity. If you have a self-deployed bridge, custom transport configuration, or heavy session usage, expect more manual decisions during the clarification step.
  • Production impact. The cutover is immediate and destructive to in-flight work. Plan a maintenance window.

Red Flags to Watch For

The skill explicitly calls out patterns that will cause problems:

  • Mixing @next Worker with stable image (or reverse)
  • Using gradual container rollout for this cutover
  • Treating await exec as command completion (it's process start)
  • Assuming cd or environment exports persist across exec calls
  • Using one retry wrapper for every error type
  • Inventing APIs like gitCheckout on core, process stdin, or undocumented helpers
  • Keeping pre-cutover process or terminal IDs after deploy
  • Forcing production cutover without user agreement

The Bottom Line

Migrating from Cloudflare Sandbox stable to @next is a significant but manageable task. The sandbox-migrate-to-next skill gives you a structured workflow that covers the audit, the code changes, the cutover, and the validation. It knows when to stop and ask for your input, and it enforces the hard rules that prevent production failures.

The goal isn't to make the migration invisible—it's to make it predictable. You'll know exactly what changed, why it changed, and how to verify it works.

Related Articles