# Scale

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:

| **Dimension**          | **What scales**                              | **Mechanisms**                                                                                                                                                                                        |
| ---------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Sandbox** <br /> (vertical)     | vCPU, RAM, and disk of a single sandbox      | • [**Custom resources**](https://www.daytona.io/docs/en/v2/sandboxes.md#resources) <br /> • [**Resource limits**](https://www.daytona.io/docs/en/v2/limits.md#sandbox-limits)                                                                          |
| **Fleet** <br /> (horizontal)     | Number of sandboxes running simultaneously | • [**Snapshot fan-out**](https://www.daytona.io/docs/en/v2/snapshots.md)                                                                                                             |
| **Workload** <br /> (concurrency) | Concurrent processes in a sandbox | • [**Sessions**](https://www.daytona.io/docs/en/v2/process-execution.md#sessions) <br /> • [**Background commands**](https://www.daytona.io/docs/en/v2/process-execution.md#start-a-background-process) <br /> • [**PTY sessions**](https://www.daytona.io/docs/en/v2/pty.md) |

## Sandbox scaling

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](https://www.daytona.io/docs/en/v2/limits.md#sandbox-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.


```python
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),
)
```

| **Parameter** | **Type** | **Description**                          |
| ------------- | -------- | ---------------------------------------- |
| **`cpu`**         | **`float`**  | Sets 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. |
| **`memory`**      | **`int`**    | In GiB.                                  |
| **`disk`**        | **`int`**    | In GiB.                                  |

- The API raises values below the [minimums](https://www.daytona.io/docs/en/v2/sandboxes.md#resources) to those minimums.


```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

// Guarantee 2 vCPUs, 4 GiB of RAM, and 16 GiB of disk for the sandbox
const sandbox = await daytona.v2.create({
  resources: { cpu: 2, memory: 4, disk: 16 },
})
```

| **Parameter** | **Type** | **Description**                          |
| ------------- | -------- | ---------------------------------------- |
| **`cpu`**         | **`number`** | Sets 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. |
| **`memory`**      | **`number`** | In GiB.                                  |
| **`disk`**        | **`number`** | In GiB.                                  |

- The API raises values below the [minimums](https://www.daytona.io/docs/en/v2/sandboxes.md#resources) to those minimums.


```bash
# Guarantee 2 vCPUs, 4 GiB of RAM, and 16 GiB of disk; --memory and --disk are MiB
daytona sandbox create --cpu 2 --memory 4096 --disk 16384
```

| **Flag** | **Type** | **Description**              |
| -------- | -------- | ---------------------------- |
| **`--cpu`**  | **`float`**  | Sets the CPU guarantee in cores. The value can be fractional. The API raises the CPU guarantee to at least 1 core per 4096 MiB of memory. |

- The API raises values below the [minimums](https://www.daytona.io/docs/en/v2/sandboxes.md#resources) to those minimums.


```bash
curl 'https://api.daytona.com/sandboxes' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "cpu": 2,
  "memory_mib": 4096,
  "disk_mib": 16384
}'
```

| **Field**     | **Type**  | **Description**              |
| ------------- | --------- | ---------------------------- |
| **`cpu`**         | **`number`**  | Sets the CPU guarantee in cores. The value can be fractional. The API raises **`cpu`** to at least 1 core per 4096 MiB of **`memory_mib`**. |
| **`memory_mib`**     | **`integer`** | In MiB.                      |
| **`disk_mib`** | **`integer`** | In MiB.                      |

- The API raises values below the [minimums](https://www.daytona.io/docs/en/v2/sandboxes.md#resources) to those minimums.



A sandbox bursts beyond its guarantee up to the platform caps: **16** vCPUs and **32** GiB of memory. The per-sandbox vCPU and memory limits lower those ceilings and cannot raise them. CPU guarantees can be fractional, as small as 0.125 cores. Usage above the guarantee is billed as measured; see [billing](https://www.daytona.io/docs/en/v2/billing.md).


```python
from daytona import Daytona
from daytona.v2 import Resources

daytona = Daytona()

# Guarantee half a core and 2 GiB, and burst up to 4 vCPUs and 8 GiB
sandbox = daytona.v2.create(
    resources=Resources(cpu=0.5, cpu_max=4, memory=2, memory_max=8),
)
```

| **Parameter** | **Type** | **Description**                         |
| ------------- | -------- | --------------------------------------- |
| **`cpu_max`**     | **`int`**    | Whole vCPUs from **`1`** to **`16`**.           |
| **`memory_max`**  | **`float`**  | In GiB, from 256 MiB to 32 GiB.         |


```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

// Guarantee half a core and 2 GiB, and burst up to 4 vCPUs and 8 GiB
const sandbox = await daytona.v2.create({
  resources: { cpu: 0.5, cpuMax: 4, memory: 2, memoryMax: 8 },
})
```

| **Parameter** | **Type** | **Description**                 |
| ------------- | -------- | ------------------------------- |
| **`cpuMax`**      | **`number`** | Whole vCPUs from **`1`** to **`16`**.   |
| **`memoryMax`**   | **`number`** | In GiB, from 256 MiB to 32 GiB. |


```bash
# Guarantee half a core and 2 GiB, and burst up to 4 vCPUs and 8 GiB
daytona sandbox create --cpu 0.5 --vcpus-max 4 --memory 2048 --mem-max 8192
```

| **Flag**      | **Type** | **Description**                     |
| ------------- | -------- | ----------------------------------- |
| **`--vcpus-max`** | **`int32`**  | Whole vCPUs from **`1`** to **`16`**.       |
| **`--mem-max`**   | **`int32`**  | In MiB, from **`256`** to **`32768`**.      |


```bash
curl 'https://api.daytona.com/sandboxes' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "cpu": 0.5,
  "vcpus_max": 4,
  "memory_mib": 2048,
  "memory_max_mib": 8192
}'
```

| **Field**     | **Type**  | **Description**                |
| ------------- | --------- | ------------------------------ |
| **`vcpus_max`**   | **`integer`** | Whole vCPUs from **`1`** to **`16`**.  |
| **`memory_max_mib`** | **`integer`** | In MiB, from **`256`** to **`32768`**. |



## Fleet scaling

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](https://www.daytona.io/docs/en/v2/snapshots.md) 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](https://www.daytona.io/docs/en/v2/macos-sandboxes.md#filesystem-snapshot).


```python
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)
```

| **Parameter** | **Type** | **Description**                                                                     |
| ------------- | -------- | ----------------------------------------------------------------------------------- |
| **`wait`**        | **`int`**    | Sets 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](https://www.daytona.io/docs/en/v2/limits.md#organization-limits) when one is set.
- The SDK does not retry a create that the limit or a saturated admission queue refuses.


```python
import asyncio

from daytona import AsyncDaytona


async def run_task(daytona: AsyncDaytona, shard: int) -> str:
    # Each task gets its own isolated sandbox from the same snapshot
    sandbox = await daytona.v2.create_from_snapshot("my-snapshot")
    response = await sandbox.process.run(f"python3 run.py --shard {shard}")

    # Delete the sandbox when the task is done
    await sandbox.delete()
    return response.stdout


async def main() -> None:
    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())
```

| **Parameter** | **Type** | **Description**                                                                     |
| ------------- | -------- | ----------------------------------------------------------------------------------- |
| **`wait`**        | **`int`**    | Sets 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](https://www.daytona.io/docs/en/v2/limits.md#organization-limits) when one is set.
- The SDK does not retry a create that the limit or a saturated admission queue refuses.


```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

async function runTask(shard: number): Promise<string> {
  // Each task gets its own isolated sandbox from the same snapshot
  const sandbox = await daytona.v2.createFromSnapshot('my-snapshot')
  const response = await sandbox.process.run(`python3 run.py --shard ${shard}`)

  // Delete the sandbox when the task is done
  await sandbox.delete()
  return response.stdout
}

// Create and run 20 sandboxes concurrently from the same snapshot
const results = await Promise.all(
  Array.from({ length: 20 }, (_, i) => runTask(i))
)
console.log(results)
```

| **Parameter** | **Type** | **Description**                                                                   |
| ------------- | -------- | --------------------------------------------------------------------------------- |
| **`wait`**        | **`number`** | Sets how many seconds **`createFromSnapshot`** waits for the sandbox to start. The default is **`60`**. When **`wait`** runs out, **`createFromSnapshot`** returns the sandbox without throwing. The returned sandbox may not have started. |

- Each create counts toward the organization's [concurrent sandbox limit](https://www.daytona.io/docs/en/v2/limits.md#organization-limits) when one is set.
- The SDK does not retry a create that the limit or a saturated admission queue refuses.


```bash
# Create each sandbox from the same snapshot (run commands concurrently as needed)
daytona sandbox create-from-snapshot my-snapshot
```


```bash
# Create each sandbox from the same snapshot (issue requests concurrently as needed)
curl 'https://api.daytona.com/sandboxes/from-snapshot' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{ "snapshot": "my-snapshot" }'
```


## Workload concurrency

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](https://www.daytona.io/docs/en/v2/preview.md).

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](https://www.daytona.io/docs/en/v2/process-execution.md#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](https://www.daytona.io/docs/en/v2/pty.md) add interactive terminals.



```python
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)
```


```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

// Start the server as a background process; the handle returns immediately
await sandbox.process.start('python3 -m http.server 8000')

// Other commands run concurrently in the same sandbox
const response = await sandbox.process.run({
  argv: ['python3', '-c', "import time, urllib.request as u; time.sleep(1); print(u.urlopen('http://localhost:8000').status)"],
})
console.log(response.stdout)
```




```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

# start returns a handle immediately while the command runs in the background
handle = sandbox.process.start("pip install numpy")

# Wait for completion and read the exit code later
result = handle.wait()
print(result.exit_code)
```


```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

// start returns a handle immediately while the command runs in the background
const handle = await sandbox.process.start('pip install numpy')

// Wait for completion and read the exit code later
const result = await handle.wait()
console.log(result.exitCode)
```



## Capacity and throughput

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

| **Control**                                   | **What it limits**                                                            | **Scope**    |
| --------------------------------------------- | ----------------------------------------------------------------------------- | ------------ |
| [**Resources**](https://www.daytona.io/docs/en/v2/sandboxes.md#resources) | Maximum vCPU, memory, and disk of a single sandbox                            | Sandbox      |
| [**Credits**](https://www.daytona.io/docs/en/v2/billing.md)               | Spending across sandboxes; creates are rejected when the balance is exhausted | Organization |

### Reclaiming capacity

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

- **Sandboxes** release compute and storage immediately on delete.
- **[Spot sandboxes](https://www.daytona.io/docs/en/v2/preemption.md#spot-sandboxes)** are deleted automatically when the platform needs capacity. See [preemption](https://www.daytona.io/docs/en/v2/preemption.md).

### Operating at scale

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

- Make creates safe to retry with an [idempotency key](https://www.daytona.io/docs/en/v2/linux-sandboxes.md#create-a-linux-sandbox): 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.

```bash
# 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'
```