Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions deploy/microvm/SIZE-TIERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Offering a MicroVM size tier

Memory is the only sizing knob this platform has, and it lives on the **image**, not the launch:
`RunMicrovmInput` carries no memory or vCPU field. So a size tier *is* an image. Offering N
sizes means publishing N images and selecting one per create.

Nothing here is optional — a tier that is built but not configured is refused at create, and a
tier that is configured but not built fails at launch.

## Prerequisites (once per account/region)

| | |
|---|---|
| Build role | `arn:aws:iam::<acct>:role/opensandbox-microvm-build`, or override `MICROVM_BUILD_ROLE_ARN` |
| Base image | `arn:aws:lambda:<region>:aws:microvm-image:al2023-1`, or override `MICROVM_BASE_IMAGE_ARN` |
| Architecture | **ARM_64 only.** `build.sh` cross-compiles to match; `publish.sh` states it explicitly so the two cannot drift |
| S3 bucket | somewhere to put the artifact zip |
| AWS CLI | with `lambda-microvms` support |

## Per tier

Every tier is the **same artifact** published under a different name with a different memory
value. Build once, publish N times.

```bash
# 1. Package + upload the artifact (once, shared by every tier)
./deploy/microvm/build.sh # → s3://<bucket>/agent-image.zip

# 2. Publish one image per tier
MICROVM_IMAGE_NAME=opensandbox-agent-prod-8192 \
MICROVM_IMAGE_MEMORY_MB=8192 \
./deploy/microvm/publish.sh s3://<bucket>/agent-image.zip
```

`publish.sh` polls until the build leaves `CREATING` and prints `latestActiveImageVersion`.
A tier is not usable until that appears.

### Tiers we offer, and the sub-2048 warning

Publish these to mirror the current runtime's tiers as closely as the platform allows:

| Tier | Why |
|---|---|
| 1024 | matches the current 1 GB tier, which is already documented as best-effort CPU |
| 2048 | smallest size that reliably gets a full vCPU |
| 4096 | the default; also the only pooled tier |
| 8192 | matches the current 8 GB tier, and is the platform ceiling |

There is no 16384 — the current runtime's 16 GB tier has no equivalent here.

`publish.sh` **warns** when `MICROVM_IMAGE_MEMORY_MB` is below 2048:

> 2048 MiB is the smallest baseline that still gets a full vCPU under Lambda's baseline-peak
> model, and peak scales to 4x it.

That warning is **expected and safe to ignore for the 1024 tier**. CPU is allocated as a
function of memory, so a 1 GB box gets best-effort CPU — which is exactly what the current
runtime's 1 GB tier already provides, so it is not a regression. Do not publish below 1024.

### Naming

**Name images per environment.** Dev and prod share an AWS account, and the image ARN is the
only ownership signal anything has. `opensandbox-agent-dev-8192` and `opensandbox-agent-prod-8192`
must be distinct images, or one environment's tooling can act on the other's boxes.

## Wiring the cell

Publishing an image does nothing on its own. The cell has to be told about it:

```bash
# /etc/opensandbox/server.env
OPENSANDBOX_MICROVM_IMAGE_ARN=arn:aws:lambda:us-east-1:<acct>:microvm-image:opensandbox-agent-prod
OPENSANDBOX_MICROVM_DEFAULT_MEMORY_MB=4096
OPENSANDBOX_MICROVM_SIZE_IMAGES="2048=arn:...:opensandbox-agent-prod-2048,8192=arn:...:opensandbox-agent-prod-8192"
```

Then restart the control plane — the config is read at startup.

- `IMAGE_ARN` is the **default** tier, and the only one the warm pool stocks.
- `SIZE_IMAGES` is every **other** tier, `mb=arn` comma-separated. A tier absent from this map
is refused at create, never silently served from the default image.
- A malformed entry is dropped with a log line rather than failing startup. That tier then
refuses instead of becoming a wrong-size sandbox — so **check the logs**, a typo is silent
apart from that line.

### DEFAULT_MEMORY_MB must match the image

`OPENSANDBOX_MICROVM_DEFAULT_MEMORY_MB` must equal the default image's actual
`minimumMemoryInMiB`. It is what metering reads:

> if it drifts from the image, every sandbox on that image is billed for the wrong size

Left at 0 it falls back to a built-in baseline of 4096. If you publish the default image at any
other size, set this explicitly.

## Verifying

On startup the control plane logs the tiers it will serve:

```
microvm: size tiers — default 4096MB pooled, cold-only: [2048 8192]
```

Then confirm end to end — an unconfigured tier must be refused, not downsized:

```bash
# a configured tier → 201
curl -X POST "$API/api/sandboxes" -H "X-API-Key: $KEY" -d '{"memoryMB":8192}'

# an unconfigured one → 400, listing what IS offered
curl -X POST "$API/api/sandboxes" -H "X-API-Key: $KEY" -d '{"memoryMB":3072}'
# {"error":"requested sandbox size is not available in this region: 3072MB was requested;
# this region offers 4096 MB, 2048, 8192"}
```

## Costs of a non-default tier

Only the default tier is pooled. Warm stock is per-image, so pooling every tier would either
multiply idle spend by the number of tiers or split one pool between them and lose the latency
the pool exists for.

A non-default tier therefore **cold-launches (~3s)** rather than being claimed from the pool.
That is the deliberate trade: one size is fast, the rest are correct.
39 changes: 32 additions & 7 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@
},
{
"group": "Test and operate",
"pages": ["agents/playground", "agents/logs"]
"pages": [
"agents/playground",
"agents/logs"
]
},
{
"group": "Examples",
Expand All @@ -84,7 +87,12 @@
"groups": [
{
"group": "Getting Started",
"pages": ["introduction", "quickstart", "how-it-works"]
"pages": [
"introduction",
"quickstart",
"how-it-works",
"migrating-from-v1"
]
},
{
"group": "Sandboxes",
Expand All @@ -95,6 +103,8 @@
"sandboxes/mounts",
"sandboxes/signed-urls",
"sandboxes/interactive-terminals",
"sandboxes/lifetime",
"sandboxes/sizes",
"sandboxes/timeout",
"sandboxes/checkpoints",
"sandboxes/templates",
Expand All @@ -108,14 +118,18 @@
"group": "Usage",
"tag": "Preview",
"expanded": true,
"pages": ["sandboxes/usage"]
"pages": [
"sandboxes/usage"
]
}
]
},
{
"group": "Browser Sessions",
"tag": "Preview",
"pages": ["browser-sessions/overview"]
"pages": [
"browser-sessions/overview"
]
},
{
"group": "Reserved Capacity",
Expand Down Expand Up @@ -159,7 +173,9 @@
"group": "Usage & Tags",
"tag": "Preview",
"expanded": true,
"pages": ["reference/typescript-sdk/usage"]
"pages": [
"reference/typescript-sdk/usage"
]
},
"reference/typescript-sdk/exec",
"reference/typescript-sdk/filesystem",
Expand Down Expand Up @@ -331,16 +347,25 @@
},
{
"group": "Resources",
"pages": ["troubleshooting"]
"pages": [
"troubleshooting"
]
},
{
"group": "Self-hosting",
"pages": ["self-hosting/overview", "self-hosting/gcp-development"]
"pages": [
"self-hosting/overview",
"self-hosting/gcp-development"
]
}
]
}
]
},
"banner": {
"content": "✨ You are viewing the **v2** SDK docs, which have not gone into effect yet. For the docs that describe the platform as it works today, go to [docs-v1.opencomputer.dev](https://docs-v1.opencomputer.dev).",
"dismissible": false
},
"logo": {
"light": "/images/logo-light.svg",
"dark": "/images/logo-dark.svg",
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/browser-automation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ If the site has a good API, use the API. A browser is slower, heavier, and flaki

## Step 1: Build a snapshot with Chromium pre-installed

Browser setup is heavy (apt packages + Chromium binary is ~500MB). Bake it into a [named snapshot](/sandboxes/snapshots) once, launch sandboxes from it in seconds.
Browser setup is heavy (apt packages + Chromium binary is ~500MB). Bake it into a [template](/sandboxes/templates) once, launch sandboxes from it in seconds.

```typescript build-snapshot.ts
import { Image, Snapshots } from "@opencomputer/sdk/node";
Expand Down Expand Up @@ -227,7 +227,7 @@ await run("npx", ["libretto", "save", "app.example.com", "--session", "login"],
// → writes /home/sandbox/.libretto/profiles/app.example.com.json
```

The profile lives on the data disk, which survives sandbox hibernation. For cross-sandbox persistence, [snapshot the sandbox](/sandboxes/snapshots) after login and launch future sandboxes from that warm snapshot — they'll boot already logged in.
The profile lives on the data disk, which survives sandbox hibernation. For cross-sandbox persistence, [checkpoint the sandbox](/sandboxes/checkpoints) after login and launch future sandboxes from that warm snapshot — they'll boot already logged in.

---

Expand Down Expand Up @@ -280,5 +280,5 @@ OC's preview-URL edge buffers response bodies — streaming chunks don't reach t
## Next steps

- Read the [libretto docs](https://libretto.sh/docs) for the full CLI + library reference.
- See [Snapshots](/sandboxes/snapshots) for how to checkpoint a warmed-up browser VM.
- See [Checkpoints](/sandboxes/checkpoints) for how to checkpoint a warmed-up browser VM.
- See [Secret Stores](/sandboxes/secrets) for scoping egress and sealing real credentials.
Loading