GET /v1/model-limits needs no API
key and returns the published limits your deployment is serving.
Per job
The upload ceiling is a default. A deployment can be configured with a different one, and that
override is not reflected in
/v1/model-limits — so if an upload is rejected below
5,000,000,000 bytes, ask your administrator what the deployment is set to.
One stale number sits elsewhere in the control plane.
- The org usage summary returns
maxColsPerJob: 500. Nothing enforces it and no job is measured against it. The column ceiling is 2,000 — what the SDK checks locally, what the worker checks on arrival, and what this page publishes.
The cell budget
Rows and columns each have a ceiling, and their product has a third. A table has to be under all three, so the wider it is the shorter it has to be. Three tables that all sit exactly on the 100,000,000-cell budget:- 1,000,000 rows × 100 columns — at the row ceiling.
- 500,000 rows × 200 columns.
- 50,000 rows × 2,000 columns — at the column ceiling.
Per day
The daily row quota counts input rows only. Output rows are billed but do not draw on it, so a
context-backed predict spends
outputRowCount of quota and bills twice that.
Quota is reserved when a job is submitted and released when it completes. A burst of concurrent
submits can therefore hit quota_exceeded before any of them has run.
Contexts and waiting
A fitted context lives 7 days from the fit that created it. Predicting against an expired one raisesfitted_context_expired; the fix is to fit again.
Blocking calls stop waiting after 900 seconds by default, and raise a Python TimeoutError.
The timeout ends the wait, not the job — the job keeps running server-side. Pass timeout= to
change it, or wait=False to take a handle instead.
Forecast
Forecast cells are counted as context rows × (covariate columns + 1), because the target column
counts too. A forecast never uses a fitted context, so every call ships the whole context
window and every call is measured against these limits in full.
What happens at each ceiling
quota_exceeded is a 429 that is not retryable. A client that retries every 429 will loop
against it; reduce what you send, or wait for the 00:00 UTC reset.
The dataset_too_large envelope names the dimension you breached, the value you sent and the
limit. If you breach several at once it names the first. Envelope fields are in
Errors.
Where each limit is checked
- Rows, columns, cells, scored rows and classes are checked in the SDK before your table is serialized. They fail in under a second and upload nothing.
- Upload bytes are not checked in the SDK. The payload is serialized and gzipped in full,
then rejected at presign with
payload_too_large. You pay the compression pass, not the transfer. - The SDK checks against a snapshot bundled in the wheel. It does not read
/v1/model-limits. Raising a limit server-side takes effect for direct REST callers at once and for the SDK only after you install a newer wheel. - Daily quota is enforced server-side only. The SDK has no local view of what you have spent today.
Next
- Errors — all 26 codes, and which four are retryable
- Usage and billing — what counts as a billable row
- The fitted context — expiry, and resuming from an id