SWR refreshInterval as a function: poll a Sume job and stop

SWR accepts a function for refreshInterval that receives the latest data. Return Sume's next_poll_after_seconds while running and 0 once terminal is true.

5 min readSume
All posts

The answer

SWR's API page says refreshInterval is disabled by default (0), that a number is a polling interval in milliseconds, and that a function receives the latest data and returns the interval in milliseconds. That is the exact shape Sume's job status needs: keep polling while the job runs, and return 0 when it is over.

Sume's status response carries terminal, result_ready and next_poll_after_seconds. Return the hint times 1000 until terminal is true, then 0.

Do not put the key in the browser

SWR runs in the browser, and a Sume API key is a server credential. The fetcher below calls a route on your own server, such as /api/sume/jobs/:id, which adds the Authorization header and forwards to https://api.sume.com/v1/jobs/:id/status. Never send Authorization: Bearer sume_live_... from client code.

The hook

The status body wraps its fields in data, so the function reads d.data. The fallback of three seconds applies before the first response arrives and when the hint is missing.

import useSWR from "swr";

const fetcher = (url: string) =>
  fetch(url).then((r) => {
    if (!r.ok) throw new Error(String(r.status));
    return r.json();
  });

export function useSumeJob(id: string | null) {
  return useSWR(id ? `/api/sume/jobs/${id}/status` : null, fetcher, {
    refreshInterval: (latest) => {
      if (!latest) return 3000;
      if (latest.data.terminal) return 0;
      return (latest.data.next_poll_after_seconds ?? 3) * 1000;
    },
  });
}

Why a function beats a fixed number

A fixed 2000 ms interval polls a ten-minute render hundreds of times. Sume's docs say the status payload's next_poll_after_seconds wins when it asks for a longer gap, and the official SDK treats its own poll interval as a floor for the same reason. Returning the hint lets the server slow you down.

Poll on the booleans (terminal, result_ready) or on sume_status, and do not mix them with the queue-shaped status field, which maps one-to-one onto sume_status for clients ported from other queue APIs.

SWR options that interact with polling (read 2026-10-03)
OptionDefaultEffect on a job poll
refreshInterval0 (disabled)Number, or function of latest data returning ms
dedupingInterval2000Requests with the same key inside 2 s are deduplicated
shouldRetryOnErrortrueFailed reads are retried
errorRetryInterval5000Gap between error retries in ms

After terminal

When terminal is true, stop polling and read the outcome from sume_status. Fetch the result route only when the job completed; failed and canceled jobs answer it with 409 job_not_completed, so read the job record for the error instead.

A server route that adds the key

The browser never sees the credential. A tiny route handler receives the job id, calls the status endpoint with the bearer token from an environment variable, and returns the JSON unchanged. Validate that the id looks like a job id and belongs to the current user before forwarding, because the key can read every job in the workspace.

The handler can also set a short cache header or none at all. SWR deduplicates identical keys inside two seconds by default, so several components using the same hook do not multiply the traffic, but the server route is still the place to rate-limit a misbehaving client.

If you need push instead of poll, Sume's job webhooks deliver terminal events to a public HTTPS URL; your server can then update its own state, and the SWR hook reads that instead of Sume directly.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume