Limits & rate limits
Limits are set per tier and enforced by the API from your key's server-side record — not from the key prefix. Every tier runs the same microVMs; limits gate concurrency, session duration, and request rate, never isolation or per-fork performance.
Per-tier limits
Section titled “Per-tier limits”| Limit | Demo | Pro | Enterprise |
|---|---|---|---|
| Concurrent sandboxes | 2 | no limit | unlimited |
| Parallel sandboxes (fan-out width) | shared self-serve | unbounded, auto-scaled | unlimited |
| Fork fan-out (per group) | up to 1000 | unbounded | unbounded |
| Max session duration | 1 hour | 24 hours | unlimited |
| Request rate | shared self-serve cap | per-tenant, high | per-tenant, custom |
"Unlimited" on Enterprise means the API applies no cap (limit 0 = no cap in
the key record). Pro has no concurrent-sandbox cap either; it is built to run at
extreme width, and capacity scales with your workload.
Width — how you fan out to hundreds or thousands. Two paths, and only the second involves the fork fan-out number above:
- Parallel sandboxes — independent sandboxes spread across the fleet,
autoscaled onto more nodes. Declare how wide you expect to fan out with
Env.expect(N)(a hint the platform provisions for — not a knob you turn); Pro has no width quota, so capacity scales with your workload. Hundreds-to-thousands of parallel rollouts — a wide GRPO run — live here. - Live-fork fan-out —
fork(count=N)clones one running parent into N copy-on-write children that share its RAM on the parent's node (≈3 ms, no cold start). Because the children pin to one node, a singleforkcall is batched.Session.fork_group(n)chunks a wider CoW group across calls transparently and enforces strict width — reach for it, not rawfork, whenever you want a group larger than one batch. Demo groups fan out to 1,000; on Pro and Enterprise the group is effectively unbounded.
How limits surface
Section titled “How limits surface”- Concurrency — creating a sandbox past your cap returns
429 quota_exceeded(on Demo, a friendly403 demo_tier_limitthat says what to do). Suspend or delete a live sandbox, or upgrade. - Request rate — exceeding your per-key rate returns
429 rate_limitedwith aRetry-Afterheader. The bucket is keyed by your key id, so another tenant on a shared egress IP can't throttle you, and rotating IPs can't dodge it. - Session duration — a sandbox that outlives your tier's max session is reaped. Persist anything you need and re-create, or suspend before the cap.
Handling rate limits
Section titled “Handling rate limits”Back off with exponential jitter and honor Retry-After:
import time, random
def with_backoff(fn, tries=5): for i in range(tries): try: return fn() except RateLimited as e: wait = e.retry_after or random.uniform(0, 0.5 * 2**i) time.sleep(wait) raiseThe collimate-rl SDK already does bounded, full-jitter backoff for
429/503, so a fanned-out GRPO group degrades gracefully instead of hammering
the API.
Next steps
Section titled “Next steps”- Authentication — tiers and the 401/429 semantics.
- Errors — the full code catalog.
- Pricing — what each tier costs.