Rate Limits
Logic64 enforces per-endpoint rate limits and generation capacity protections to ensure fair throughput for all users. When a limit is reached the API returns HTTP 429 with a Retry-After header. This page documents every published limit, what a 429 response looks like, and the backoff strategy clients should follow.
Why rate limits
Rate limits serve three purposes:
- Fairness across users. A single client that hammers the download or repackage endpoints cannot degrade service for everyone else. Per-user windows ensure consistent throughput regardless of load distribution.
- Capacity protection. Generation is compute-intensive. Bounding the request rate prevents any one account from exhausting server-side resources and causing latency spikes for concurrent sessions.
- Runaway cost prevention. Generation requests trigger resource-intensive server-side work. Limits act as a circuit breaker against accidental retry loops that would otherwise accumulate costs silently.
Per-endpoint limits
Limits are enforced per authenticated user, evaluated over a rolling one-minute window. Endpoints not listed below are either explicitly not rate-limited or have no published limit.
| Method | Endpoint | Limit | Notes |
|---|---|---|---|
| GET | /bundles/:id | No published limit | Returns bundle metadata. |
| GET | /bundles/:id/download | 10 req / min / user | Streams the bundle ZIP. |
| POST | /bundles/:id/ack | Not rate-limited | Idempotent pull confirmation. |
| POST | /projects/:id/bundles/repackage | 3 req / min / user | Re-emits a bundle without an LLM call. |
The GET /bundles/:id metadata endpoint has no published limit but is still subject to general abuse-prevention policies. The ACK endpoint POST /bundles/:id/ack is intentionally not rate-limited — retrying a failed ACK must always succeed without backoff.
429 responses
Every rate-limit rejection returns HTTP 429 with a Retry-After header. The value is in seconds and represents the minimum wait before the next request will be accepted. Clients must respect this value — retrying before the window expires will produce another 429.
HTTP/1.1 429 Too Many RequestsRetry-After: 12Content-Type: application/json{"error": "Too many requests"}
Retry-Afteris always an integer number of seconds.- The response body always contains an
errorstring for programmatic detection. - On repackage, the response may additionally include a
codefield (e.g."TOO_MANY_REQUESTS") for structured error handling.
Generation capacity
Generation requests are processed through a server-side queue. The queue has a configured maximum depth. When the depth is exceeded — typically during sustained high demand — the API returns HTTP 429 with a Retry-After header rather than silently dropping or holding the request open indefinitely.
During high demand, new generation requests may be temporarily rejected with 429 while the queue drains. The Retry-After value indicates the recommended wait. Studio surfaces this as a “server busy” message with an automatic retry countdown.
This behavior is by design: a hard rejection at intake is preferable to accepting a request into an unbounded queue where it could wait for an indeterminate amount of time with no feedback to the caller.
Plan generation caps
In addition to per-minute endpoint limits, generation throughput is capped at the account level based on your plan:
| Plan | Generation cap |
|---|---|
| Hobby | 3 generations / 24-hour rolling window |
| Developer | Unlimited |
| Architect Pro | Unlimited |
Hobby caps reset on a 24-hour rolling basis from the time of your first generation in the window. When the cap is reached, subsequent generation requests return HTTP 429 until the window resets. See plans and pricing for full feature comparison.
Best practices
- Always respect
Retry-After. Read the header value on every 429 and wait at least that many seconds before retrying. Ignoring it produces another 429 immediately and wastes a retry slot. - Apply exponential backoff with jitter. After the
Retry-Afterwindow, add a small random delay (jitter) before each subsequent retry. This prevents synchronized retry storms when many clients hit the limit at the same time. - Use
Idempotency-Keyon repackage. Send a client-generated UUID in theIdempotency-Keyheader onPOST /projects/:id/bundles/repackagerequests. If the same key is received within 60 seconds, the server returns the original bundle ID without creating a duplicate or consuming an additional rate-limit slot. This lets you safely retry a repackage after a network failure without risking double-billing or duplicate bundles. - Cap total retries. Set a maximum retry count (typically 3–5) and surface a clear error to the user if all retries are exhausted. An open-ended retry loop can exhaust your per-minute window and delay recovery.
Backoff example
The following pseudocode shows the recommended pattern: read Retry-After, add jitter, and cap total attempts.
# Pseudocode — Retry-After-aware exponential backoff with jitterattempt = 0while attempt < MAX_RETRIES:response = api.call(request)if response.status != 429:breakretry_after = int(response.headers.get("Retry-After", 2 ** attempt))jitter = random.uniform(0, 0.3 * retry_after)sleep(retry_after + jitter)attempt += 1
The jitter term (random.uniform(0, 0.3 * retry_after)) spreads retries across a 30% window above the server-mandated delay, which is sufficient to break lock-step retry patterns under realistic load.
Next steps
With rate limits understood, continue with the full API reference or explore how the streaming protocol works during generation.