> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opencomputer.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Elasticity

> Dynamically scale sandbox memory and CPU — automatically, manually, or via the in-VM API

A sandbox's memory and CPU can be resized at runtime. The platform's recommended path is **Autoscaling** — opt the sandbox in once and we resize it for you based on observed memory pressure. Lower-level controls are also available if you want to drive sizing yourself or freeze it.

CPU scales proportionally to memory in all modes (1 vCPU per \~4 GB up to 16 GB / 4 vCPU). The permissible memory tiers are:

| Memory | vCPU            |
| ------ | --------------- |
| 1 GB   | 1 (best-effort) |
| 4 GB   | 1               |
| 8 GB   | 2               |
| 16 GB  | 4               |

If you want a sandbox to **stay at a fixed size**, see [Locking Resources](#locking-resources).

## Autoscaling

Opt a sandbox into the per-sandbox autoscaler and the platform resizes it for you based on observed memory pressure. Autoscale is **opt-in per sandbox** and **disabled by default**.

This is the recommended way to size a sandbox: turn it on once with bounds you're comfortable with, then leave it. Manual `scale` and the in-VM API are escape hatches for cases where the autoscaler isn't a good fit (e.g. you want a hard guarantee for a benchmark, or you're scripting your own logic).

### Enable

<CodeGroup>
  ```typescript TypeScript theme={null}
  await sandbox.setAutoscale({
    enabled: true,
    minMemoryMB: 1024,
    maxMemoryMB: 16384,
  });
  ```

  ```python Python theme={null}
  await sandbox.set_autoscale(
      enabled=True,
      min_memory_mb=1024,
      max_memory_mb=16384,
  )
  ```

  ```bash CLI theme={null}
  oc sandbox autoscale sb-abc123 --on --min 1024 --max 16384
  ```

  ```bash HTTP theme={null}
  curl -sf -X PUT "$API/api/sandboxes/$SANDBOX_ID/autoscale" \
    -H "X-API-Key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"enabled": true, "minMemoryMB": 1024, "maxMemoryMB": 16384}'
  ```
</CodeGroup>

`minMemoryMB` and `maxMemoryMB` must be values from the tier table above. The autoscaler keeps the sandbox between these bounds, in tier steps.

### Behavior

* **Scale up**: when the sandbox's 1-minute average memory utilization exceeds 75 %, jump to the next tier. 60-second cooldown between up-events.
* **Scale down**: when **all** of the 1-min, 5-min, and 15-min utilization averages stay below 25 %, drop one tier. 5-minute cooldown between down-events. Down requires at least 15 minutes of low-utilization data, so a brief idle pause won't shrink you.
* **Manual override**: any explicit `scale` call disables autoscale on that sandbox. Re-enable explicitly via `setAutoscale({ enabled: true, ... })` (or the equivalent in any SDK) if you want it back.

### Disable

<CodeGroup>
  ```typescript TypeScript theme={null}
  await sandbox.setAutoscale({ enabled: false });
  ```

  ```python Python theme={null}
  await sandbox.set_autoscale(enabled=False)
  ```

  ```bash CLI theme={null}
  oc sandbox autoscale sb-abc123 --off
  ```

  ```bash HTTP theme={null}
  curl -sf -X PUT "$API/api/sandboxes/$SANDBOX_ID/autoscale" \
    -H "X-API-Key: $API_KEY" \
    -d '{"enabled": false}'
  ```
</CodeGroup>

### Inspect

<CodeGroup>
  ```typescript TypeScript theme={null}
  const cfg = await sandbox.getAutoscale();
  // { sandboxID: "sb-...", enabled: true, minMemoryMB: 1024, maxMemoryMB: 16384 }
  ```

  ```python Python theme={null}
  cfg = await sandbox.get_autoscale()
  # {"sandboxID": "sb-...", "enabled": True, "minMemoryMB": 1024, "maxMemoryMB": 16384}
  ```

  ```bash CLI theme={null}
  oc sandbox autoscale sb-abc123
  # Autoscale enabled for sb-abc123 (1024–16384 MB)
  ```

  ```bash HTTP theme={null}
  curl -sf "$API/api/sandboxes/$SANDBOX_ID/autoscale" -H "X-API-Key: $API_KEY"
  # {"sandboxID":"sb-...","enabled":true,"minMemoryMB":1024,"maxMemoryMB":16384}
  ```
</CodeGroup>

## Manual Scaling (Control Plane)

When you want to resize once — predictable size for a benchmark, a one-off scale-up before a known-heavy task, an operator response to an alert — call `scale` from your application or operator tooling:

<CodeGroup>
  ```typescript TypeScript theme={null}
  await sandbox.scale({ memoryMB: 4096 });
  ```

  ```python Python theme={null}
  await sandbox.scale(memory_mb=4096)
  ```

  ```bash CLI theme={null}
  oc sandbox scale sb-abc123 4096
  ```

  ```bash HTTP theme={null}
  curl -sf -X POST "$API/api/sandboxes/$SANDBOX_ID/scale" \
    -H "X-API-Key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"memoryMB": 4096}'
  ```
</CodeGroup>

A manual scale **disables autoscale** on the sandbox — explicit user intent overrides the loop. Re-enable it later if you want size to track load again.

The endpoint can return:

* **403 `scaling_locked`** — the sandbox is locked. See [Locking Resources](#locking-resources).
* **409 `oom_floor`** — the requested size would force a guest OOM-kill because the current working set exceeds it. Free memory inside the guest, then retry.
* **402 Payment Required** — the requested size exceeds your plan cap.

## In-VM Scaling

Sandboxes expose an internal metadata API at `http://169.254.169.254` that lets code **inside** the VM scale itself. Useful for workload-aware scripts where the workload knows its own demand better than the platform autoscaler can infer (e.g. "scale up before this build, back down after").

<Note>
  This endpoint is only reachable from inside the sandbox. It is not exposed through the control plane API or SDKs.
</Note>

### Scale Memory

Send a `POST` to `/v1/scale` with the desired memory in MB. CPU is adjusted proportionally.

```bash theme={null}
curl -s -X POST http://169.254.169.254/v1/scale \
  -H "Content-Type: application/json" \
  -d '{"memoryMB": 4096}'
```

### Check Current Limits

```bash theme={null}
curl -s http://169.254.169.254/v1/limits
```

### Example: Rust Compilation

Rust builds are memory-hungry. You can alias `cargo` to scale up before compilation and scale back down after:

```bash theme={null}
alias cargo='_cargo_scaled'
_cargo_scaled() {
  # Scale up to 16GB / 4 vCPU before build
  curl -sf -X POST http://169.254.169.254/v1/scale \
    -H "Content-Type: application/json" -d '{"memoryMB": 16384}'

  # Run the actual cargo command
  command cargo "$@"
  local exit_code=$?

  # Scale back down to 4GB / 1 vCPU
  curl -sf -X POST http://169.254.169.254/v1/scale \
    -H "Content-Type: application/json" -d '{"memoryMB": 4096}'

  return $exit_code
}
```

Add this to your sandbox's `~/.bashrc` or inject it via `sandbox.exec.run` so every `cargo build`, `cargo test`, etc. automatically gets the extra resources.

### Example: Custom Scaling Loop

A simple shell script that monitors memory pressure and scales automatically. Useful when you want fine-grained control inside the sandbox itself; for the platform-managed equivalent see [Autoscaling](#autoscaling) above.

```bash theme={null}
#!/bin/sh
SCALE_API="http://169.254.169.254/v1/scale"
MIN_MB=1024
MAX_MB=8192
SCALE_UP_THRESHOLD=80
SCALE_DOWN_THRESHOLD=30
COOLDOWN=30
last_scale=0

while true; do
  mem_total=$(awk '/MemTotal/{print $2}' /proc/meminfo)
  mem_avail=$(awk '/MemAvailable/{print $2}' /proc/meminfo)
  usage_pct=$(( (mem_total - mem_avail) * 100 / mem_total ))
  total_mb=$((mem_total / 1024))
  now=$(date +%s)
  elapsed=$((now - last_scale))

  if [ $usage_pct -gt $SCALE_UP_THRESHOLD ] && [ $elapsed -gt $COOLDOWN ]; then
    new_mb=$((total_mb * 2))
    [ $new_mb -gt $MAX_MB ] && new_mb=$MAX_MB
    if [ $new_mb -gt $total_mb ]; then
      echo "usage=$usage_pct% -> scaling UP to ${new_mb}MB"
      curl -sf -X POST "$SCALE_API" \
        -H "Content-Type: application/json" \
        -d "{\"memoryMB\":$new_mb}"
      last_scale=$now
    fi
  elif [ $usage_pct -lt $SCALE_DOWN_THRESHOLD ] && [ $total_mb -gt $MIN_MB ] && [ $elapsed -gt $COOLDOWN ]; then
    new_mb=$((total_mb / 2))
    [ $new_mb -lt $MIN_MB ] && new_mb=$MIN_MB
    if [ $new_mb -lt $total_mb ]; then
      echo "usage=$usage_pct% -> scaling DOWN to ${new_mb}MB"
      curl -sf -X POST "$SCALE_API" \
        -H "Content-Type: application/json" \
        -d "{\"memoryMB\":$new_mb}"
      last_scale=$now
    fi
  fi

  sleep 5
done
```

## Locking Resources

If you want a sandbox to **stay at a fixed size** — predictable billing, a benchmark, a long-running pinned workload — lock it. Locking blocks both manual scaling and autoscaling on the sandbox.

<CodeGroup>
  ```typescript TypeScript theme={null}
  await sandbox.setScalingLock(true);
  ```

  ```python Python theme={null}
  await sandbox.set_scaling_lock(True)
  ```

  ```bash CLI theme={null}
  oc sandbox lock sb-abc123
  ```

  ```bash HTTP theme={null}
  curl -sf -X PUT "$API/api/sandboxes/$SANDBOX_ID/scaling-lock" \
    -H "X-API-Key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"locked": true}'
  ```
</CodeGroup>

While locked:

* `scale` returns **403** `scaling_locked`
* `setAutoscale({ enabled: true })` returns **403** `scaling_locked`
* The autoscaler skips the sandbox

Locking automatically disables autoscale on the sandbox, so you have a single user-facing toggle. Unlocking does **not** auto-re-enable autoscale; turn it back on explicitly if you want it.

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Unlock
  await sandbox.setScalingLock(false);

  // Inspect
  const lock = await sandbox.getScalingLock();
  // { sandboxID: "sb-...", locked: false }
  ```

  ```python Python theme={null}
  # Unlock
  await sandbox.set_scaling_lock(False)

  # Inspect
  lock = await sandbox.get_scaling_lock()
  # {"sandboxID": "sb-...", "locked": False}
  ```

  ```bash CLI theme={null}
  oc sandbox unlock sb-abc123
  oc sandbox lock-status sb-abc123
  ```

  ```bash HTTP theme={null}
  # Unlock
  curl -sf -X PUT "$API/api/sandboxes/$SANDBOX_ID/scaling-lock" \
    -H "X-API-Key: $API_KEY" \
    -d '{"locked": false}'

  # Inspect
  curl -sf "$API/api/sandboxes/$SANDBOX_ID/scaling-lock" -H "X-API-Key: $API_KEY"
  # {"sandboxID":"sb-...","locked":false}
  ```
</CodeGroup>
