Skip to content

Scale

View as Markdown

Daytona sandboxes are designed to be created and operated at high volume. A single sandbox scales up by resizing its reserved resources, a fleet scales out by running many sandboxes at once, and each sandbox runs multiple processes concurrently.

Unlike request-based execution environments, a sandbox is a long-lived computer: processes are not terminated after a request completes, so running services, open connections, and background workers persist until the sandbox stops.

Scale operates along three dimensions:

DimensionWhat scalesMechanisms
Sandbox (vertical)vCPU, RAM, and disk of a single sandboxCustom resources
Resize
Fleet (horizontal)Number of sandboxes running at the same timeSnapshot fan-out
Fork
Linked sandboxes
Workload (concurrency)Concurrent processes inside a single sandboxSessions
Async commands
PTY sessions

Sandbox scaling changes the resources of a single sandbox: vCPU, memory, and disk. Resources are reserved when the sandbox is created and can be changed later by resizing.

Resources are set differently depending on how the sandbox is created:

  • From an image: set resources on the create parameters
  • From a snapshot: the sandbox inherits the resources defined on the snapshot

Resizing changes the allocation of an existing sandbox. On a running sandbox, CPU and memory can be increased without interruption. Decreasing CPU or memory, or increasing disk, requires the sandbox to be stopped first. Disk can only grow, and GPU allocation cannot be resized. Every allocation must stay within your organization’s per-sandbox limits.

from daytona import CreateSandboxFromImageParams, Daytona, Resources
daytona = Daytona()
# Reserve 2 vCPUs, 4GiB of RAM, and 8GiB of disk for the sandbox
sandbox = daytona.create(
CreateSandboxFromImageParams(
image="ubuntu:22.04",
resources=Resources(cpu=2, memory=4, disk=8),
)
)

Fleet scaling raises the number of sandboxes running at the same time. The unit of scale is the sandbox itself: instead of packing unrelated workloads into one environment, create one sandbox per user, task, or agent.

Sandboxes are isolated from each other, so a fleet scales linearly: each new sandbox adds capacity without contention, and a failure in one sandbox does not affect the others.

The mechanisms differ in what state each new sandbox starts with:

MechanismStarting stateUse
Snapshot fan-outFilesystem from the snapshot; hot snapshots add memory stateAny number of identical environments from one prepared snapshot
ForkFilesystem and memory of a running VM sandboxBranch a live environment into independent copies
Linked sandboxesFresh environment, co-located with a parent on the same runnerCoordinated groups with a local network between parent and children

Snapshot fan-out is the default pattern: prepare the environment once, capture it as a snapshot, and create any number of sandboxes from it. Each sandbox starts with the environment intact, with nothing to reinstall. Sandboxes created from a hot snapshot start with processes already running.

Forking duplicates a running VM sandbox, filesystem and memory included, into an independent sandbox. Where snapshot fan-out distributes a prepared baseline, forks branch live state: each fork continues from the exact point the original was at. Forking is supported for VM sandboxes (Linux VM and Windows) only.

Linked sandboxes attach ephemeral child sandboxes to a parent. Children are scheduled on the same runner as the parent and share a link network, so the group communicates over local connections. One parent may have many children, and deleting the parent deletes all of them.

import asyncio
from daytona import AsyncDaytona, CreateSandboxFromSnapshotParams
async def run_task(daytona: AsyncDaytona, shard: int) -> str:
# Each task gets its own isolated, ephemeral sandbox
sandbox = await daytona.create(
CreateSandboxFromSnapshotParams(snapshot="my-env-snapshot", ephemeral=True)
)
response = await sandbox.process.exec(f"python3 run.py --shard {shard}")
# Stop deletes the ephemeral sandbox
await sandbox.stop()
return response.result
async def main():
async with AsyncDaytona() as daytona:
# Create and run 20 sandboxes concurrently from the same snapshot
results = await asyncio.gather(*(run_task(daytona, i) for i in range(20)))
print(results)
asyncio.run(main())

Workload concurrency runs multiple processes inside a single sandbox. A single sandbox can run an API server, a database, and background workers side by side: all processes share the sandbox’s filesystem and network, and exposed ports are reachable through previews.

A sandbox runs concurrent processes through sessions. Each session is an independent shell with its own state: working directory, environment variables, and command history.

Commands within a session run sequentially, so parallelism comes from running multiple sessions. Commands started with run_async return immediately and run in the background, and PTY sessions add interactive terminals.

from daytona import Daytona, SessionExecuteRequest
daytona = Daytona()
sandbox = daytona.create()
# Each session is an independent shell inside the same sandbox
sandbox.process.create_session("server")
sandbox.process.create_session("worker")
# The server runs in the background while the worker session stays free
sandbox.process.execute_session_command("server", SessionExecuteRequest(
command="python3 -m http.server 8000",
run_async=True,
))
response = sandbox.process.execute_session_command("worker", SessionExecuteRequest(
command="curl -s http://localhost:8000",
))
print(response.output)

Fleet size and creation rate operate within your organization’s limits. Both are tier-based and raised by verification steps or by contacting support.

ControlWhat it limitsScope
Compute poolTotal vCPU, RAM, and storage across all running sandboxesOrganization, per region and sandbox class
Per-sandbox limitsMaximum vCPU, RAM, and storage of a single sandboxSandbox
Rate limitsSandbox creation, lifecycle operations, and API requests per minuteOrganization

To scale beyond the shared compute pool, bring your own compute (BYOC) attaches your own runner nodes in custom regions, which have no concurrent resource usage limits.

The compute pool is shared by running sandboxes only: stopped, paused, and archived sandboxes free their reserved CPU and memory back to the pool. A fleet can therefore be much larger than the pool, as long as the concurrently running subset fits.

Reclamation runs automatically. Ephemeral sandboxes delete themselves on stop, and the auto-stop, auto-pause, and auto-delete intervals reclaim capacity from idle sandboxes without manual intervention. See persistence for details.

At high creation rates, two practices keep an application within its rate limits.

  • Handle rate limit errors: the SDKs raise DaytonaRateLimitError when a limit is exceeded, and the returned headers indicate how long to wait before retrying the request.
  • Use webhooks to track sandbox state changes instead of polling. Webhooks deliver state changes as they happen, so no requests are spent checking for status.