Skip to main content
Concurrency is the number of requests your organization can have processing at once, sync requests and async tasks together. Your plan sets the number of slots: with 10, an 11th sync request sent while 10 are still processing gets a 429 (CONCURRENCY_LIMIT_EXCEEDED) rather than queueing.

Rate limits vs. concurrency limits

Free tier accounts are limited to 1 concurrent request. Upgrade for multi-threaded workloads. See the pricing table for concurrency limits per plan. cloro applies two types of limit depending on the endpoint: Monitor endpoints are subject to both.

Monitoring concurrency with headers

Monitor responses that pass request validation include these headers (link resolution excepted): On a 20-slot plan with 3 requests in flight:

Monitoring rate limits with headers

Every authenticated response includes rate limit headers: The limit is per endpoint per API key — each /v1/* path has its own independent 1,000 RPS bucket, and the counter resets every second. After one request to /v1/monitor/chatgpt:

Credit headers

A successful (200) sync monitor response also carries the credit balance and the amount charged for that request: Alert before you run low:
Error responses, link resolution and the async endpoints don’t carry these headers. For async-only workloads, read your balance from GET /v1/credits instead. For how credits are allocated, expire, and are priced, see Billing & credits and Providers.

Latency header

Every response carries X-Latency-Ms — the milliseconds the API spent on the request, from arrival to the start of the response. It excludes network transit, so wall-clock timing on your side is always higher.
Async tasks report the equivalent in the task body as latencyMs — see asynchronous requests.

Using headers for optimization

Throttle from the headers you already have: pause when X-RateLimit-Remaining nears zero, since it resets every second, and treat X-Concurrency-Remaining as a snapshot from when the request arrived, not a live count. When you do hit a 429, back off exponentially rather than re-sending at once. Its error code tells you which limit you hit and when it clears.

Implementation patterns

Pattern 1: Async with webhooks

For large-scale processing, submit tasks through the batch endpoint and take the results on a webhook. cloro queues the tasks and runs them within your plan’s concurrency limit (task processing limits); batching only keeps the submission itself from becoming one HTTP request per task.
See the batch endpoint examples for the full response, and receiving deliveries for the webhook handler.

Pattern 2: Concurrent workers

For real-time processing where you want immediate results, run as many workers as your plan has concurrency slots, each making direct API calls. The JavaScript version reuses makeRequestWithRetry from above.

Common questions

Why am I getting 429 rate limit errors?

Three causes, each with its own error.code: more simultaneous monitor requests than your plan’s slots (CONCURRENCY_LIMIT_EXCEEDED), over 1,000 requests per second to one endpoint (RATE_LIMIT_EXCEEDED), or a full async queue (QUEUE_LIMIT_EXCEEDED). The error handling guide says when each clears and how to back off.

How do I check my concurrency limit?

Read X-Concurrency-Limit on a monitor response, or call the async status endpoint for your account’s concurrency stats.

Can I increase my concurrency limit?

Yes. Self-serve plans can be upgraded directly in the dashboard — the new limit applies immediately, no support ticket required. If you need concurrency above the highest self-serve tier, email info@cloro.dev for an enterprise quote.

Does higher concurrency delay my logs or dashboards?

No. Dashboard log ingestion runs independently from request processing. See where to find request logs for how soon entries appear.

Can I burst above my concurrency limit?

No. The limit is hard — the (N+1)th simultaneous request gets a 429 immediately rather than queueing. Use the async API if you want cloro to handle queueing for you instead of managing burst capacity yourself.

What’s the best way to handle large batches of requests?

For non-time-sensitive batches, use Pattern 1: Async with webhooks: submit through the batch endpoint (limits per request), let cloro run the tasks up to your plan’s limit, and take results on the webhook. When you need results in real time, use Pattern 2: Concurrent workers: stay within your plan’s concurrency limit, watch X-Concurrency-Remaining, and back off exponentially on 429s.