Limits

Concurrency by plan, start-rate limits, default and max TTLs, disk sizes, regions, and fair use.


Sandal enforces limits per-account to keep the fleet fair and the bare-metal capacity pool healthy for everyone. All limits below are defaults, Enterprise plans can request higher ceilings.

Concurrency by plan#

Maximum number of simultaneously running (non-paused) sandboxes, runners, and simulator sessions, combined, per account.

PlanConcurrent sandboxesConcurrent runnersConcurrent simulators
Free521
Builder50205
Team25010025
Enterprisecustomcustomcustom

Paused sandboxes don't count against concurrency, only actively-running instances do. A snapshot with zero active/provisioned resources is effectively free real estate against your limits.

Start-rate limits#

To protect warm-pool capacity and prevent runaway loops from a single account, sandbox/runner/simulator creation is rate-limited per minute.

PlanSandbox creates/minRunner job starts/minSimulator creates/min
Free1052
Builder1005010
Team50025050
Enterprisecustomcustomcustom

Exceeding the start-rate limit returns 429 rate_limited with a Retry-After header. Batch creation (e.g. spinning up a 50-agent fleet) should ramp over a few seconds rather than firing all at once, see Fair use below for the recommended pattern.

TTL (time to live)#

Every sandbox, runner, and simulator has a TTL after which it's automatically paused (sandboxes) or torn down (runners, simulators) if not explicitly kept alive.

ResourceDefault TTLMax TTL (configurable)
Sandbox (active)10 minutes idle → auto-pause24 hours
Sandbox (paused snapshot)30 days1 year (Team+), indefinite (Enterprise)
GitHub Actions runnerJob duration + 5 min grace6 hours
Simulator session15 minutes idle → teardown4 hours
Code interpreter session5 minutes idle → teardown1 hour

Set a custom TTL at creation time (sandal.sandboxes.create({ ttl: "2h" })); requests above the max TTL for your plan are clamped, not rejected.

Disk sizes#

ResourceDefault diskMax disk
Sandbox5 GB100 GB (Builder+), 500 GB (Enterprise)
GitHub Actions runner14 GB (matches GitHub-hosted default)100 GB
Simulator (iOS/Android)8 GB32 GB

Disk beyond the default is billed as additional provisioned storage; see Pricing.

Regions#

Sandal runs in two regions today, both on bare-metal capacity (no shared hyperscaler zones):

  • EU, Falkenstein/Helsinki (Hetzner), Roubaix (OVH)
  • US, Ashburn, VA (Leaseweb) and dedicated Mac mini racks (macOS runners/simulators, US-only at launch)

Select region explicitly (region: "eu" / region: "us") or omit it to let Sandal route to the region closest to your API caller. Cross-region snapshot restore is supported but adds transfer latency; same-region restore hits the sub-1s cold-create target.

macOS runners and iOS simulators are US-only while we bring up EU Mac mini capacity, EU availability is tracked on the status page.

Fair use#

Sandal is priced for real agent workloads, not for probing the limits. Fair use expectations:

  • Ramp bursts, don't spike them. Creating hundreds of sandboxes in the same second, even under your rate limit, can trip anti-abuse heuristics designed to catch runaway loops. Spread fleet startup over a few seconds using the SDK's built-in backoff.
  • Pause what you're not using. Provisioned RAM on idle-but-active sandboxes is billed; if an agent is between turns, sb.pause() rather than leaving it hot. TTL auto-pause is a backstop, not the intended workflow.
  • Don't use sandboxes as permanent storage. Sandboxes and their snapshots are for compute, not as a substitute for object storage, expect throttling on accounts using snapshot storage as a primary data store at high volume.
  • Simulator/runner sessions are for testing and CI, not mining or proxying. Standard AUP violations (crypto mining, network abuse, credential stuffing, running the sandbox as an open relay) result in immediate suspension regardless of plan.
  • Report capacity issues, don't route around them. If you're hitting concurrency or start-rate limits on legitimate workload, talk to us about an Enterprise ceiling rather than sharding across accounts, account sharding to evade limits is a ToS violation.

All limits on this page reflect current production configuration and are evidence-gated the same way pricing is, verified against qualification runs, not aspirational numbers. If you hit a limit that doesn't match what's documented here, that's a bug, file an issue.