> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chariot.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate limits & concurrency

> How Chariot limits concurrent requests per plan, and how to handle limit errors.

Chariot limits how many requests you can run **at the same time** (concurrency), scaled to your plan. There is no fixed requests-per-second cap. The control is on simultaneous in-flight generations.

## How concurrency works

Each workspace may have a fixed number of TTS generations running concurrently. When a request starts it takes a slot; when it finishes it releases the slot. If all slots are busy, the next request is rejected immediately with `429` rather than being queued.

The limit is scoped to your **workspace** and driven by your **plan tier**.

## Limits by plan

| Plan    | Concurrent TTS requests |
| ------- | ----------------------- |
| Free    | 2                       |
| Starter | 3                       |
| Startup | 10                      |
| Scale   | 25                      |

<Note>
  These are the current defaults and can change as plans evolve. Check your plan in the dashboard for the value that applies to your workspace.
</Note>

## The 429 response

When you exceed your concurrency limit:

```json theme={null}
{
  "statusCode": 429,
  "error": "HTTPException",
  "message": "Concurrent request limit exceeded (2) for tts.standard on the current plan"
}
```

If your plan does not include the product at all, you get `403` instead:

```json theme={null}
{
  "statusCode": 403,
  "error": "HTTPException",
  "message": "Product model tts.standard is not available on the current plan"
}
```

## Handling limits

The API does not queue requests or send a `Retry-After` header, a `429` is an immediate rejection. Handle it on the client:

* **Cap your in-flight requests** to your plan's concurrency limit so you rarely hit `429` in the first place.
* **Retry with exponential backoff and jitter** when you do, e.g. 0.5s, 1s, 2s, 4s with random jitter.
* **Use a worker pool** sized to your limit rather than firing all requests at once.

```python Python theme={null}
import time, random, requests

def synthesize_with_retry(payload, key, max_retries=5):
    for attempt in range(max_retries):
        r = requests.post(
            "https://api.chariot.in/v1/tts",
            headers={"chariotai-api-key": key},
            json=payload,
        )
        if r.status_code != 429:
            r.raise_for_status()
            return r
        sleep = (2 ** attempt) * 0.5 + random.random() * 0.25
        time.sleep(sleep)
    raise RuntimeError("Concurrency limit exceeded after retries")
```

## Need more headroom?

If you consistently hit your concurrency limit, upgrade your plan for more slots, or contact [support@chariot.in](mailto:support@chariot.in) to discuss higher limits.
