Managed lifecycle

Coordinate Sandbox creation, commands, and cleanup as durable steps in a function run.

Access-gated beta. The low-level TypeScript API below follows the access-gated Sandbox beta. The planned step.sandbox.typescript helper has no published call shape yet.

Use durable Sandbox steps when isolated code belongs to a longer function run. Inngest records each operation’s result, so a resumed function can continue after completed steps. The API you choose determines which lifecycle and cleanup actions your function must handle.

APIWhat Inngest handlesWhat you handle
step.sandbox.create() and other low-level stepsDurable operation results, safe retries, readiness polling by default, and step failuresWhen to pause, resume, snapshot, clone, and destroy the Sandbox; cleanup after permanent failure
inngest.sandboxesImmediate Sandbox requests and bounded readiness pollingRetries, cancellation, and cleanup in your server process
Planned step.sandbox.typescriptStarts a Sandbox, runs TypeScript, and stops the Sandbox in one callPlanned; no beta API

Use a Sandbox in a durable function

Add the Sandbox middleware to a TypeScript v4 client. Each step.sandbox operation takes a stable step ID. This example creates a Sandbox, runs a command, and destroys the Sandbox on the successful path.

import { Inngest } from "inngest";
import { sandboxMiddleware } from "inngest/experimental";

const inngest = new Inngest({
  id: "sandbox-lifecycle",
  middleware: [sandboxMiddleware()],
});

export const runInSandbox = inngest.createFunction(
  {
    id: "run-in-sandbox",
    triggers: { event: "sandbox/job.requested" },
  },
  async ({ event, step }) => {
    const sandbox = await step.sandbox.create("create-sandbox", {
      name: `job-${event.data.jobId}`,
      vcpu: 1,
      memoryMb: 1024,
      runningTimeout: "60s",
    });

    const result = await sandbox.commands.run(
      "run-command",
      ["node", "-e", "console.log('done')"],
      { timeout: "30s" },
    );

    await sandbox.destroy("destroy-sandbox");

    return { exitCode: result.exitCode, stdout: result.stdout };
  },
);

Use a stable, Sandbox-safe job ID in the event. A completed step replays its result, including the Sandbox object returned by Create. This avoids creating another Sandbox when the function resumes after a later step. It does not keep the guest process or filesystem alive if the Sandbox itself is lost.

Create waits for RUNNING by default. If readiness times out, the Sandbox may still exist. When cleanup needs an ID even if readiness fails, create with runningTimeout: false, then call sandbox.waitUntilRunning("wait-for-sandbox", { timeout: "60s" }) as a separate step.

Clean up after failure

The example's Destroy step runs only if execution reaches it. If the function fails after all retries, use an onFailure handler or a separate cleanup function that can retrieve the Sandbox ID. Store the ID somewhere that handler can read after Create. The failure handler runs as a separate function; a JavaScript finally block in the main function does not replace this cleanup path.

For immediate server-side calls through inngest.sandboxes, use try/finally and call sandbox?.destroy() in finally. The direct client has no durable step replay.

Destroy removes the Sandbox filesystem, processes, and retained process output. Persist artifacts outside the Sandbox before destroying it. Destroy may first return TERMINATING; teardown continues after the API accepts the request.

Pause, resume, and reuse state

Pause releases the live runtime into a private checkpoint. Resume returns the same Sandbox ID with its filesystem, memory, and remaining runtime. The current beta allows one hour of active runtime per Sandbox; time spent paused does not consume it. Use the returned running Sandbox before making another command, file, log, or process call.

A user snapshot keeps a copy of memory, disk, environment, image, and resource settings while the source Sandbox continues running. Clone creates a new Sandbox ID from a ready snapshot. Snapshot creation and readiness are separate phases. A wait timeout does not cancel the snapshot being created.

The Sandbox filesystem persists through pause and resume, and a snapshot clone receives the captured filesystem. S3-backed persistent filesystem mounts can share a backing path across different Sandboxes, including clones; those mounts are a separate storage choice from the Sandbox’s private filesystem.

Retries and uncertain outcomes

Let unexpected step.sandbox errors escape the function. Inngest retries operations the middleware marks safe and records a failure when retries are exhausted or an operation is unsafe to repeat. An operation_ambiguous error means a command, process start, or signal may have happened without a confirmed response. Inspect the Sandbox or the operation's external effect before deciding whether to repeat it.

A durable step records the operation result; it does not promise that a Sandbox, guest process, or retained output survives a lost runtime. Inspect the current Sandbox state with Get when work resumes after a long wait or external interruption.

Sandbox operations used as durable steps appear with the function's other steps in its run trace.

One-call TypeScript execution

A planned step.sandbox.typescript call will start a Sandbox, run TypeScript, and stop it automatically. This planned path is for one isolated task that does not keep a Sandbox between steps.

This page describes isolated microVM Sandboxes. Deployment preview environments are called branch deploys.