Runway polling: 5 seconds, jitter, backoff vs Sume next_poll_after

Runway recommends polling tasks every 5 seconds or more with jitter and exponential backoff. Sume returns next_poll_after_seconds. A Python poller for both.

5 min readSume
All posts

Runway recommends polling a task no faster than every 5 seconds, adding jitter, and backing off exponentially on non-200 responses, and it warns against a fixed setInterval because API latency can bunch requests. Sume goes one step further: the job status response can include next_poll_after_seconds, and clients should honor it when present and back off otherwise.

The two sets of rules

The Runway rules in order: a 5-second floor, jitter, exponential backoff on errors and no fixed-interval timers. The reason given is that latency makes a fixed timer too frequent on some ticks.

Polling guidance, read 2026-10-02
ItemRunwaySume `/v1/jobs`
Interval5 seconds or morenext_poll_after_seconds when present
JitterRecommendedNot stated on the pages read; add it anyway
ErrorsExponential backoff on non-200Back off when the hint is absent
Fixed timersAvoidAvoid
Push alternativeNot covered hereSigned webhooks; keep polling as fallback

A poller that follows both

This poller waits for a Sume job, honors the hint and uses jitter. Set SUME_API_KEY and pass a job id.

import os, random, sys, time
import requests

BASE = "https://api.sume.com"
TERMINAL = {"completed", "failed", "canceled"}

def wait(job_id, timeout=600):
    headers = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
    deadline = time.time() + timeout
    delay = 5.0
    while time.time() < deadline:
        r = requests.get(f"{BASE}/v1/jobs/{job_id}/status", headers=headers, timeout=30)
        if r.ok:
            body = r.json()
            if body.get("status") in TERMINAL:
                return body
            hint = body.get("next_poll_after_seconds")
            delay = float(hint) if hint else 5.0
        else:
            delay = min(delay * 2, 60)
        time.sleep(max(5.0, delay) + random.uniform(0, 1.5))
    raise TimeoutError("still running; cancel the job if you no longer need it")

if __name__ == "__main__":
    print(wait(sys.argv[1]))

Prefer a push

Polling is the fallback, not the plan. For many jobs, use a signed webhook and sweep with polling only for the ones that never call back.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume