Can polling Sume job status hit the rate limit? Read budget math

Reads and writes have separate Sume budgets. Worked numbers for polling every accepted job per plan, plus a delay function that reads ratelimit headers.

5 min readSume
All posts

Polling job status will not exhaust a Sume key's rate limit if you poll at the suggested 2-second pace, because status reads draw from a read budget that is forty times the write budget. Even polling every accepted job on a plan once per second stays well under the per-minute read number. The limit you are more likely to meet is queue_full, which is generation capacity, not request rate.

The arithmetic below uses only figures from the Sume docs. A job counts toward polling while it is queued or processing, and the most jobs a workspace can hold in those states is its accepted job capacity (concurrency plus queue).

Worked numbers

Each cell is accepted jobs times polls per minute. Writes per minute are 120, 300, 600 and 1200 for the same plans, so submits and cancels are the budget to watch, not status reads. Enterprise is contract-specific, and until a number is provisioned resolves to the Scale row.

Reads per minute if every accepted job is polled, plan figures from docs.sume.com read 2026-10-02
PlanAccepted jobsReads/min at 2s pollsReads/min at 1s pollsRead budget/min
Free61803604800
Pro24720144012000
Startup481440288024000
Scale1203600720048000

What still goes wrong

The docs also say to read ratelimit-remaining rather than counting requests yourself, since the headers describe whichever budget the current request spent from.

  • One key shared by many services: the budget is per API key, so a second service polling with the same key spends the same read bucket.
  • Polling without next_poll_after_seconds: hammering a status URL at 100 ms is allowed by the budget on paper but wastes the budget for everything else.
  • Reading the wrong signal: a 429 names its scope in error.details.scope, read or write. A write 429 on submit does not mean your poller is too fast.

A delay function that reads the headers

It returns how long to sleep before the next status read. A missing header is treated as unknown, not zero, because Number(null) is 0 and would look like an empty budget.

// Read the budget the response just spent from. Headers can be absent, and
// Number(null) is 0, so test for null before converting.
const num = (res, name) => {
  const v = res.headers.get(name);
  return v === null ? null : Number(v);
};

export function nextPollDelayMs(res, hintSeconds = 2) {
  const base = Math.max(2, hintSeconds) * 1000;
  const limit = num(res, "ratelimit-limit");
  const left = num(res, "ratelimit-remaining");
  const reset = num(res, "ratelimit-reset");
  if (res.status === 429) {
    const wait = num(res, "retry-after") ?? reset ?? 5;
    return wait * 1000;
  }
  if (limit && left !== null && reset !== null && left < limit * 0.1) {
    return Math.max(base, reset * 1000); // under 10% left: wait for the window
  }
  return base;
}

Limits

I tested the function with hand-made responses: no headers gave 2000 ms, healthy headers gave the hint, 900 of 12000 remaining waited the 30-second reset, and a 429 used retry-after. Those are not live headers. The read multiple is a deployment setting, and the docs say ratelimit-limit on the response is the authority for the deployment you call, so the table is the shipped default and not a guarantee. Unauthenticated requests get a much smaller read bucket, so never poll without a key.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume