Skip to main content

Limits

This page is the single owner of the API's numeric caps and rate quotas. For per-endpoint request/response schemas and the error.code list, see ReDoc; for how to handle each error, see Errors.

Input length per task

All six per-task POST /v1/tasks/{task}/predict endpoints accept 1–500,000 bp. Sequences must contain only A/C/G/T/N (case-insensitive); oversized, undersized, or out-of-alphabet inputs are rejected with 422 validation_failed before any GPU work. Request body cap: 16 MiB.

The expression model uses a fixed 9,198 bp TSS-centered window (±4,599 bp). Off-length sequences are accepted (the tokenizer truncates or pads to this window), but predictions on non-TSS-centered or off-length input are not guaranteed to be biologically meaningful. If you have raw genomic input where the TSS isn't pre-known, server-side annotation→expression chaining can be enabled per account.

Latency

Rough sync latency at the recommended input size, on a warm model.

TaskSync latency at recommended sizeWhen to go async
Promoter / enhancer / chromatin0.3–10 sinputs above 100,000 bp
Splice0.3–10 sinputs above 250,000 bp
Annotation1–60 sinputs above 30,000 bp
Expression (fixed 9,198 bp window)0.5–3 sn/a — sync is always safe

Cold start

If a task's model isn't already loaded into GPU memory, the first request pays a model-load cost. The response carries meta.cold_start: true and meta.model_load_time_ms. Cold start adds 5–15 s for the smaller models and 30–90 s for expression and annotation. Subsequent calls are warm.

Sync delivery: timeout and guidance

Sync delivery (the default, no Prefer header) is best-effort within the upstream HTTP read timeout of 300 seconds. A request that takes longer than that is terminated by the edge proxy and surfaces to your client as a connection reset or 504 gateway_timeout. The body in this case is the proxy's, not the unified {error: {...}} envelope; this is the only place where that happens. Pick async whenever you expect a request to push past ~60 s.

Hard sync cap

The six per-task POST /v1/tasks/{task}/predict endpoints enforce no hard sync cap: each accepts sync up to its per-task max (see "Input length per task" above). The one exception is the composite find-genes-and-predict-expression workflow (POST /v1/workflows/find-genes-and-predict-expression): submitted synchronously above 50,000 bp it returns 413 sync_too_large. Submit it with Prefer: respond-async (as the MCP server's find_genes_and_predict_expression tool always does) to lift that cap. No other endpoint emits sync_too_large.

Use Prefer: respond-async when your input exceeds the threshold below. These are calibrated against typical inference times. Sync still works under them, but bursty traffic plus GPU contention can push individual requests past the 300 s proxy window without warning.

TaskRecommended async above
Promoter100,000 bp
Splice250,000 bp
Enhancer100,000 bp
Chromatin100,000 bp
Annotation30,000 bp
Expression (TSS-centered)n/a — input is the fixed 9,198 bp window, so sync is always safe

If sync is critical for your workload and these guidelines push more traffic to async than you'd like, contact us; we can profile your distribution and tune the proxy timeout for your account.

Per-key quotas

Three limiters run side by side. Each is configured per partner; your account owner tells you the values issued for your key. Defaults for the partner tier:

SettingDefault for partner tierEnforced?
Concurrent in-flight requests2Yes. Exceeding the cap returns 429 too_many_requests with Retry-After: 1.
Per-minute request rate60Yes. Token bucket; capacity = rate / 6 (10-second burst, default 10). An empty bucket returns 429 too_many_requests with Retry-After set to approximately the seconds until the next token.
Edge per-IP cap10 r/s burst 20 on api.*Yes. At the edge, returns 429 too_many_requests with the unified {error: {...}} envelope (see errors).

RateLimit-* headers (every authenticated response)

The application emits the IETF httpapi-ratelimit-headers draft set on every authenticated 2xx and on every 429 from this service, so you can pace from header state without inferring rate from 429s:

HeaderMeaning
RateLimit-LimitToken-bucket capacity (= rate_per_minute / 6).
RateLimit-RemainingTokens left after this request, integer.
RateLimit-ResetSeconds until the bucket refills to full.
RateLimit-Policy<capacity>;w=60, capacity per 60-second window.
Retry-AfterOn 429 only, seconds until at least one token is available.

Pacing guidance

  • Pace at ~80% of your issued RateLimit-Limit to leave headroom for bursts; serialize a small worker pool against your concurrency cap rather than firing N parallel requests at it.
  • The token bucket and concurrency semaphore are independent: a 429 can come from either. Both carry the same RateLimit-* spine, but only the rate-bucket 429 has a Retry-After calibrated against refill time; the concurrency 429 uses Retry-After: 1.

Async result store

Async job results are retained for 24 h from last activity, then expire. A fetch after the TTL (or after a service restart) returns 410 job_expired, so retrieve results promptly and re-submit if a job has expired.


Back to the workflow: REST API guide · Tasks.