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 bursting beyond its guaranteed resources, a fleet scales out by running many sandboxes at once, and each sandbox runs multiple processes concurrently.

Scale operates along three dimensions:

DimensionWhat scalesMechanisms
Sandbox
(vertical)
vCPU, RAM, and disk of a single sandbox• Custom resources
• Resource limits
Fleet
(horizontal)
Number of sandboxes running simultaneously• Snapshot fan-out
Workload
(concurrency)
Concurrent processes in a sandbox• Sessions
• Background commands
• PTY sessions

Sandbox scaling sets the resources of a single sandbox: vCPU, memory, and disk. The resource envelope is fixed when the sandbox is created; there is no resize operation.

The requested resources are a guaranteed floor, reserved at placement; beyond it the sandbox uses idle host capacity up to its resource limits, which default to the platform caps.

Size the guarantee for the workload’s average, and let bursting absorb the peaks. For a fixed shape with no bursting, set every limit equal to its request.

Guarantee CPU, memory, and disk when creating a sandbox.

from daytona import Daytona
from daytona.v2 import Resources
daytona = Daytona()
# Guarantee 2 vCPUs, 4 GiB of RAM, and 16 GiB of disk for the sandbox
sandbox = daytona.v2.create(
resources=Resources(cpu=2, memory=4, disk=16),
)
ParameterTypeDescription
cpufloatSets the CPU guarantee in cores. The value can be fractional. The API raises the CPU guarantee to at least 1 core per 4 GiB of memory.
memoryintIn GiB.
diskintIn GiB.
  • The API raises values below the minimums to those minimums.

Fleet scaling raises how many sandboxes run at once. The unit of scale is the sandbox: instead of packing unrelated workloads into one environment, create one per user, task, or agent.

Each sandbox is a hardware-isolated microVM, so a fleet scales linearly: each sandbox adds capacity without contention, and a failure in one does not affect others. Creation is fast and asynchronous, so scale on demand: create when work arrives, delete when done.

Snapshot fan-out starts each unit of work from the memory and disk of one prepared snapshot, so any number of identical environments run from the same state. Snapshot fan-out works with Linux sandboxes. macOS sandboxes start from a disk image instead: see macOS snapshots.

from concurrent.futures import ThreadPoolExecutor
from daytona import Daytona
daytona = Daytona()
def run_task(shard: int) -> str:
# Each task gets its own isolated sandbox from the same snapshot
sandbox = daytona.v2.create_from_snapshot("my-snapshot")
response = sandbox.process.run(f"python3 run.py --shard {shard}")
# Delete the sandbox when the task is done
sandbox.delete()
return response.stdout
# Create and run 20 sandboxes concurrently from the same snapshot
with ThreadPoolExecutor(max_workers=20) as pool:
results = list(pool.map(run_task, range(20)))
print(results)
ParameterTypeDescription
waitintSets how many seconds create_from_snapshot waits for the sandbox to start. The default is 60. When wait runs out, create_from_snapshot returns the sandbox without raising. The returned sandbox may not have started.
  • Each create counts toward the organization’s concurrent sandbox limit when one is set.
  • The SDK does not retry a create that the limit or a saturated admission queue refuses.

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.

Every command runs as a process: run starts a process and waits for it, while start returns a handle immediately and the process continues in the background. Sessions are shared shells: commands in a session run sequentially and share state, so parallelism comes from separate sessions or background processes. Pseudo terminal (PTY) sessions add interactive terminals.

from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create()
# Start the server as a background process; the handle returns immediately
sandbox.process.start("python3 -m http.server 8000")
# Other commands run concurrently in the same sandbox
response = sandbox.process.run(argv=[
"python3", "-c",
"import time, urllib.request as u; time.sleep(1); print(u.urlopen('http://localhost:8000').status)",
])
print(response.stdout)

Fleet size operates within per-sandbox platform caps and your organization’s credit balance.

ControlWhat it limitsScope
ResourcesMaximum vCPU, memory, and disk of a single sandboxSandbox
CreditsSpending across sandboxes; creates are rejected when the balance is exhaustedOrganization

Delete sandboxes when their work is done to release compute and storage:

  • Sandboxes release compute and storage immediately on delete.
  • Spot sandboxes are deleted automatically when the platform needs capacity. See preemption.

At high creation rates, two practices keep an application efficient:

  • Make creates safe to retry with an idempotency key: a retried create with the same key returns the same sandbox instead of minting a new one.
  • Wait with long-polls, not tight polling. The SDKs block on create until the sandbox runs. On the API, wait long-polls one sandbox, and the batch wait endpoint waits on up to 200 sandboxes over one connection, returning once one reaches the target state or timeout_ms elapses.
Terminal window
# Wait for one sandbox to reach running without tight polling
curl 'https://api.daytona.com/sandboxes/{sandboxId}?wait=running' \
--header 'Authorization: Bearer YOUR_API_KEY'
# Wait on a whole batch over one connection (up to 200 IDs)
curl 'https://api.daytona.com/sandboxes/batch-wait?ids={sandboxId1},{sandboxId2},{sandboxId3}&wait=running&timeout_ms=60000' \
--header 'Authorization: Bearer YOUR_API_KEY'