Sume ratelimit-remaining and retry-after: a fetch wrapper in JS

Sume responses can carry ratelimit-limit, ratelimit-remaining, ratelimit-reset and retry-after. A fetch wrapper that backs off on 429 and keeps submits safe.

5 min readSume
All posts

Sume public API responses can include ratelimit-limit, ratelimit-remaining, ratelimit-reset and retry-after. On a 429, wait retry-after seconds if it is present, otherwise back off. Retry an unsafe submit only with the same Idempotency-Key, so the retry returns the original job and cannot bill twice.

Two kinds of 429

The code is the signal. rate_limited means too many requests in the current window, so slow down. queue_full means workspace concurrency and queue capacity are both full, so no new paid job is accepted until a running or queued one finishes or is canceled. A queue_full retry loop does not help; wait for your own jobs to complete.

CodeMeaningClient action
rate_limitedWindow is exhaustedSleep retry-after, then retry
queue_fullQueue and concurrency are fullWait for a job to finish, then submit
provider_capacity_exceededProvider dispatch queue is fullRetry later with the same key

The wrapper

It retries only on 429 and 503, honors retry-after, caps at four attempts, and requires an idempotency key for POST so a retry cannot create a second paid job.

export async function sumeFetch(path, init = {}, tries = 4) {
  const method = init.method ?? 'GET';
  if (method === 'POST' && !init.headers?.['Idempotency-Key'])
    throw new Error('POST needs an Idempotency-Key');
  for (let i = 0; ; i++) {
    const res = await fetch('https://api.sume.com' + path, {
      ...init,
      headers: {
        Authorization: `Bearer ${process.env.SUME_API_KEY}`,
        'Content-Type': 'application/json',
        ...init.headers,
      },
    });
    if (![429, 503].includes(res.status) || i === tries - 1) return res;
    const wait = Number(res.headers.get('retry-after')) || 2 ** i;
    await new Promise((r) => setTimeout(r, wait * 1000));
  }
}

Use the headers proactively

ratelimit-remaining tells you how much of the window is left before you hit a 429, and ratelimit-reset tells you when it returns. A batch runner can slow itself when remaining is low instead of waiting for a rejection.

Remember that the headers may be absent on some responses, so treat them as hints and keep the 429 handling in place.

What not to retry

Do not retry 400, 401, 402 or 409 automatically. Those mean the request, key, balance or job state needs a human or a code change. A 402 insufficient_credits retried in a loop only repeats the same refusal.

Related posts

More in Developers

All Developers posts

Written by Sume