# Limits

These are the limits the service enforces today, and why each one exists. They aren't
performance promises. The operator can change the values marked "default".

## Sessions

| Limit | Value | Why |
|---|---|---|
| Open sessions per project | 2 (default) | A session takes a place on a shared model server, not a whole GPU. |
| Open sessions per account | 4 (default) | The same, across all of an account's projects. |
| Places per model server | shown as `capacity` in `yb models --ready` | A few sessions take turns on one server. |
| Your share of one model server | all but one of its places (default) | Someone else can always get a place. Going over fails with `slot_share`. |
| Session length | 240 minutes (default) | For longer work, open a new session. |
| Time to connect after opening | 60 seconds (default) | An unused session gives back its place and its reserved credit. |
| Connected but idle | 5 minutes without an observation | The session closes with `idle_expired`, and frees its place. Open a new one when the robot resumes. |
| Session pass | lasts about 15 minutes; the SDK renews it at half-life | A leaked pass stops working soon. A short platform outage doesn't end your session: the SDK keeps retrying until the pass is about to expire. |
| Sessions opened per project | 120 per hour | Reuse one session for many requests. |
| Spending cap per session | $1,000 (default) | Limits what one mistake can cost. |

## Requests

| Limit | Value | Why |
|---|---|---|
| Message size | 8 MiB | One LIBERO observation is about 300 KB (measured). |
| Array size | 2,097,152 values, up to 4 dimensions | Oversized arrays are refused before they use memory. |
| Deadline (`max_action_age_ms`) | 20 to 30,000 ms; 2,000 by default; at least the model's minimum | An answer older than this is dropped. Answers the model server drops as late aren't charged. A deadline below the model's minimum (120 ms for π0.5, 20 ms for the `transport-demo` sandbox) is refused with `deadline_too_short`, because no answer could arrive in time. |
| Late answers in a row | 10 | Then the session closes with `too_many_expired`: the deadline is too short for the model. |
| Model runs per session | at most the session's request limit | Answers dropped as late aren't charged, but they count toward the limit, because the model ran for them. |
| Waiting observations per session | 1 | A newer observation replaces one that hasn't started. |
| Unread answers per session | 32 | Code that stops reading loses its session, instead of slowing everyone down. |
| Invalid observations in a row | 20 | Then the session closes with `too_many_rejections`. |
| Task length | 1,000 characters | Tasks are short, such as "put the bowl on the plate". |
| Request body sent to the platform | 1 MiB | Platform requests are small. |

## Accounts

| Limit | Value |
|---|---|
| Projects per account | 5 |
| Key lifetime | 90 days; create a new key before the old one expires |
| Sign-in and account attempts | 30 per hour per network address, and 10 per 15 minutes per email |
| Verification emails | 3 per hour |
| Credit purchases started | 10 per hour per project, and 10 per hour per account (default) |
| One credit purchase | $25 to $100 (default) |

## Not limited

- The number of moves in one answer. You pay per request, not per move.
- Idle time in an open session is never charged. A connected session that sends nothing
  for 5 minutes still closes, so its place is free for someone else.
