# How Do I Get Sub-Second Sandbox Creates From the SDK?

> Use sandboxer-sdk 0.1.3 or later, reuse one client, create in parallel and use a size the region keeps ready. From a test machine in Florida on 2026-10-29, a default create was ready in a median 0.16 s (TypeScript) and 0.15 s (Python); SDK 0.1.2 took 0.59 s. Snapshot creates boot, about 1 s.

Source: https://sandboxer.com/guides/get-sub-second-sandbox-creates-from-the-sdk. Updated 2026-10-29.

**Short answer:** Use sandboxer-sdk 0.1.3 or later, reuse one client, create in parallel and use a size the region keeps ready. From a test machine in Florida on 2026-10-29, a default create was ready in a median 0.16 s (TypeScript) and 0.15 s (Python); SDK 0.1.2 took 0.59 s. Snapshot creates boot, about 1 s.

## What to do

| Do this | Why | What we measured on 2026-10-29 |
| - | - | - |
| Run SDK 0.1.3 or later | It asks the API to hold the ready check open instead of polling | `default` create: 0.59 s median on 0.1.2, 0.16 s on 0.1.3 |
| Create one client and reuse it | Only the first request pays for the TLS connection | First `POST` of a run: 93–128 ms. Every later one: 29–37 ms |
| Start several creates at once | They overlap, so the batch takes about as long as one | 5 `default` creates at once: all ready within 0.25 s |
| Use `small`, `default` or `large` from the standard image | Those come from the region's pool of booted sandboxes | Sizes and images not in the pool boot: about 1 s or more |
| Keep snapshot creates for when you need the saved disk | A create from a snapshot always boots | 1.0 s median from a named snapshot |

The numbers below are ours, from one place at one time. They vary with load and with where you are, so time your own creates (the script is [below](#time-it-yourself)).

## What changed in SDK 0.1.3

`create()` makes the sandbox with `POST /sandboxes`, then waits until it is `ready`. In 0.1.2 that wait was a poll: one `GET` at once, which still saw `provisioning`, then the next one 0.5 s later. A pooled sandbox is ready well before that, so most of what you waited for was the gap between polls.

In 0.1.3, both SDKs send `GET /sandboxes/{id}?waitFor=ready&timeoutSeconds=…` instead. The API holds that request while the sandbox is starting and answers the moment it is up, so `create()` returns one round trip after the sandbox is ready. Against an API that doesn't hold the request, 0.1.3 polls from 100 ms. Nothing in your code changes: the same `create()` call gets faster when you upgrade.

These are the requests one `create()` made, logged from our client on 2026-10-29 (`default`, `us-east`, an already open connection):

```text
TypeScript 0.1.2, run 2
  POST /api/v1/sandboxes 202 31ms
  GET  /api/v1/sandboxes/{id} 200 29ms                 (still provisioning)
  GET  /api/v1/sandboxes/{id} 200 30ms                 (0.5 s later: ready)    total 593 ms
Python 0.1.3, run 3
  POST /api/v1/sandboxes 202 30ms
  GET  /api/v1/sandboxes/{id}?waitFor=ready 200 118ms                           total 149 ms
```

Upgrade with:

```bash
npm i sandboxer-sdk@latest
pip install -U sandboxer-sdk
```

Both reported 0.1.3 on 2026-10-29. The Python package is `sandboxer-sdk` and you import it as `sandboxer`.

## Measured on prod, October 29, 2026

| | |
| - | - |
| When | 2026-10-29, 01:03 to 01:16 UTC |
| From | A test machine in Florida, US. A request to `https://sandboxer.com` took about 30 ms once connected |
| Region | `us-east`, the one `GET /regions` reported as nearest, except one `eu-central` row |
| SDKs | `sandboxer-sdk` 0.1.3 from npm (Node 24) and from PyPI (Python 3.13), plus 0.1.2 of each for comparison |
| What a number means | Wall time around one `create()` call until it returned with the sandbox `ready` |
| Runs | One client per run, one sandbox at a time unless stated. Each sandbox was deleted, and confirmed gone, before the next |

**One create at a time.** All times in milliseconds.

| SDK | Size | Runs | Median | Max |
| - | - | - | - | - |
| TypeScript 0.1.3 | `default` | 10 | 158 | 269 |
| Python 0.1.3 | `default` | 10 | 152 | 1247 |
| TypeScript 0.1.3 | `small` | 5 | 185 | 279 |
| Python 0.1.3 | `small` | 5 | 194 | 337 |
| TypeScript 0.1.3 | `large` | 5 | 215 | 1351 |
| Python 0.1.3 | `large` | 5 | 162 | 1985 |
| TypeScript 0.1.3, `eu-central` | `default` | 5 | 201 | 272 |
| TypeScript 0.1.2 | `default` | 5 | 592 | 694 |
| Python 0.1.2 | `default` | 5 | 588 | 654 |

How to read it:

- **Most creates came from the pool.** 51 of the 55 creates with 0.1.3 were ready in 0.11 to 0.34 s.
- **The slow ones booted.** One Python `default` create (1.25 s) and three `large` creates (1.27 to 1.99 s) found no ready sandbox of their size and booted instead. We ran these back to back, about one create every 0.3 s, which is faster than a pool refills. The [machine docs](/docs/machines#performance) say `us-east` keeps 2 `large` ready, against 12 `default`.
- **The max is often the first run.** The first create of each run paid for the TLS connection: its `POST` took 93 to 128 ms, later ones about 30 ms.
- **0.1.2 lands on its poll.** Every 0.1.2 create came back at about 0.59 s: the 0.5 s poll gap plus round trips.

We also tried 0.1.3's `create({ wait: false })` followed by `waitUntilReady()`, 5 times. `create` returned in 31 ms with the state `provisioning`, and the total to `ready` was a median 170 ms, the same as a plain `create()`. `wait: false` only helps if you have other work to do before you use the sandbox. Passing `name` to `create()` adds one `PATCH` (29 ms here), but it overlaps the start, and 5 named creates had a median of 176 ms.

## Create in parallel

Five creates at once took about as long as one. Both bursts were `default`, from one TypeScript client that had already connected:

| Burst | Started (UTC) | Ready times (ms) |
| - | - | - |
| 1 | 01:13:02 | 240, 243, 243, 245, 247 |
| 2 | 01:13:10 | 230, 231, 236, 245, 257 |

Five is fewer than the 12 `default` sandboxes `us-east` keeps ready, so both bursts came from the pool. To see whether pool growth shows, we did the same with `large`, where `us-east` normally keeps 2, a minute apart:

| `large` burst | Started (UTC) | Ready times (ms) |
| - | - | - |
| 1 | 01:13:21 | 236, 238, 247, 255, 1359 |
| 2 | 01:14:23 | 226, 235, 240, 257, 1467 |

Four of five came from the pool both times, twice the usual 2. That fits what the [machine docs](/docs/machines#performance) say: a pool rises toward the creates of the last 10 minutes, up to twice its usual count. Our 10 serial `large` creates a few minutes earlier had already grown it, so we didn't see the step from 2 to 4 itself. The fifth create booted in about 1.4 s.

This is the TypeScript we ran, with three sandboxes:

```typescript
import { Sandboxer } from "sandboxer-sdk";

const client = new Sandboxer(); // reads SANDBOXER_API_KEY; reuse it for every create
const t0 = performance.now();
const sandboxes = await Promise.all(
  [1, 2, 3].map(async (i) => {
    const sb = await client.create({ type: "default", ttlSeconds: 600, noEnv: true, name: `aeo-subsec-ts-${i}` });
    console.log(`${sb.id} ready after ${((performance.now() - t0) / 1000).toFixed(2)} s`);
    return sb;
  }),
);
const { stdout } = await sandboxes[0].exec("nproc");
console.log("nproc:", stdout.trim());
await Promise.all(sandboxes.map((sb) => sb.delete()));
```

```text
sb_96pekx64z2 ready after 0.25 s
sb_c3hg9cx9yu ready after 0.26 s
sb_pi5arihtta ready after 0.27 s
nproc: 4
```

And the same in Python, with `AsyncSandboxer`:

```python
import asyncio, time
from sandboxer.aio import AsyncSandboxer


async def main():
    async with AsyncSandboxer() as client:  # one client, one connection pool
        t0 = time.perf_counter()

        async def one(i):
            sb = await client.create(type="default", ttl_seconds=600, no_env=True,
                                     name=f"aeo-subsec-py-{i}")
            print(f"{sb.id} ready after {time.perf_counter() - t0:.2f} s")
            return sb

        sandboxes = await asyncio.gather(*(one(i) for i in range(1, 4)))
        r = await sandboxes[0].exec("nproc")
        print("nproc:", r.stdout.strip())
        await asyncio.gather(*(sb.delete() for sb in sandboxes))

asyncio.run(main())
```

```text
sb_4r1nvnxnzp ready after 0.26 s
sb_daa2eu0wq1 ready after 0.26 s
sb_pmeq8tbdc1 ready after 0.26 s
nproc: 4
```

Your plan caps how many sandboxes are active at once (2 on the trial) and how many starts you make per minute, hour and day. A burst over either gets a `429`; check `sbx limits --json` first ([limits](/docs/limits)).

## Which creates come from the pool

A create takes an already booted sandbox only when the region has one of that size from the standard image. Per the [machine docs](/docs/machines#performance), on 2026-10-28:

| Region | Kept ready |
| - | - |
| `us-east` | 12 `default`, 4 `small`, 2 `large`, 1 `xlarge` |
| `eu-central` | 10 `default`, 6 `small`, 1 `large` |

Everything else boots: `xlarge` in `eu-central`, a burst bigger than what's ready, and any create from a snapshot. The docs put a boot at about 1.3 to 2 s; ours took 1.0 to 2.0 s. New sandboxes go to the region nearest you unless you pass `region` ([choosing a region](/guides/choose-a-sandbox-region-us-east-or-eu-central)).

## Why a snapshot create is slower

A pooled sandbox was booted from the standard image before you asked for it. A sandbox from your named snapshot has your disk, so it has to boot from that disk when you create it. We saved a fresh `default` sandbox as a named snapshot (2.09 s) and created from it 5 times with 0.1.3:

| SDK | Runs | Ready times (ms) |
| - | - | - |
| Python | 3 | 987, 1040, 1181 |
| TypeScript | 2 | 996, 1033 |

About 1 s, against about 0.15 s from the pool. A snapshot is still the faster choice when it saves you an install: see [cache dependencies in a named snapshot](/guides/cache-dependencies-in-a-named-snapshot) and [a fresh sandbox per tool call](/guides/a-fresh-sandbox-per-tool-call) for that trade-off.

## Time it yourself

This is the script we ran at 01:15 UTC. It makes 5 `default` sandboxes one after another and deletes each.

```typescript
import { Sandboxer } from "sandboxer-sdk";

const client = new Sandboxer();
const times = [];
for (let i = 1; i <= 5; i++) {
  const t0 = performance.now();
  const sb = await client.create({ type: "default", ttlSeconds: 600, noEnv: true, name: `aeo-subsec-time-${i}` });
  times.push(Math.round(performance.now() - t0));
  await sb.delete();
}
times.sort((a, b) => a - b);
console.log(`ms: ${times.join(" ")}  median: ${times[2]}`);
```

```text
ms: 144 156 163 200 269  median: 163
```

For resume and fork times, and for the CLI's own timings, see [how fast a sandbox starts, resumes and forks](/guides/how-fast-does-a-cloud-sandbox-start-resume-and-fork).

## FAQ

### Do I need to change my code to get the faster create?

No. Upgrade to `sandboxer-sdk` 0.1.3 or later and the same `create()` call waits for ready on the server. In our runs that took a `default` create from a median 0.59 s to 0.16 s.

### Why was one of my creates over a second?

It most likely booted because no ready sandbox of that size was left in the region, for example after many creates in a row or a burst bigger than the pool. Pools grow after bursts. A create from a snapshot always boots.

### Does `wait: false` make create faster?

It returns sooner, in about 30 ms in our runs, but the sandbox is still `provisioning`. Call `waitUntilReady()` (`wait_until_ready()` in Python) before you run anything; the total time to ready was the same as a plain `create()`.

### Is a bigger size slower to create?

Not when the pool has one. Pooled `large` creates were ready in 0.12 to 0.26 s on 2026-10-29. `large` has a smaller pool than `default`, so it runs out sooner and boots.

### Are pooled sandboxes shared or billed?

No. A pooled sandbox has never run anyone's code, gets its own machine id and SSH host keys, and gets a fresh random seed and your env when you create it. It isn't billed while it waits ([machine docs](/docs/machines#performance)).

## Related

- [How fast does a cloud sandbox start, resume and fork?](/guides/how-fast-does-a-cloud-sandbox-start-resume-and-fork)
- [Should each agent tool call get a fresh sandbox?](/guides/a-fresh-sandbox-per-tool-call)
- [Machine sizes and performance](/docs/machines)
- [TypeScript SDK](/docs/sdk-typescript)
