subscribeFormatRun timeline: true doubles your status reads
Setting timeline: true on subscribeFormatRun reads the phase timeline on every poll, doubling requests. Read budget math, 429 behavior and when to turn it on.

With timeline: true, subscribeFormatRun and waitForRun read the Format run's phase timeline on every poll as well as its status, so the wait makes twice as many requests for the same run. Reads have their own rate-limit budget, so the extra calls cannot 429 your run creates, but they do spend read budget and add load. Leave it off unless a person is actually watching phases.
Numbers and behavior come from Waiting for runs and jobs and Authentication, read 2026-10-02.
What does the timeline give you?
status says a Format run is processing. The phase timeline says what it is doing: preparing, running, finalizing, each with a timestamp and a status. It arrives on the onStatus snapshot as snapshot.timeline. It is a phase timeline, not a log stream: agent output, tool calls and sandbox internals are never published.
It applies to Format runs only. timeline: true is ignored for family: "action" and "agent", whose receipts report events_url: null because they have no events route.
const run = await subscribeFormatRun({
client,
path: { handle: "acme", slug: "product-promo" },
body: { input: { product_url: "https://shop.example.com/p/8823" } },
timeline: true,
onStatus: (status, snapshot) => {
const phase = snapshot.timeline?.at(-1);
console.log(status, phase?.phase, phase?.status);
},
});How much read budget does that burn?
Reads and writes are separate budgets, and a read is any GET. The per-minute numbers below are from the Authentication page; the polling arithmetic after them is mine, using the SDK's 2-second default poll interval.
| Plan | Writes per minute | Reads per minute |
|---|---|---|
| Free | 120 | 4800 |
| Pro | 300 | 12000 |
| Startup | 600 | 24000 |
| Scale | 1200 | 48000 |
Will many concurrent runs hit the ceiling?
One waiter polling every 2 seconds makes about 30 status reads a minute; with the timeline on, about 60. On the Free plan's 4800 reads a minute, that is roughly 160 waiters without the timeline and 80 with it, before anything else you do with GET requests, since lists and result fetches share the same bucket. Concurrent runs are also capped by the plan's generation concurrency, so real counts are usually lower.
The SDK jitters polls, because several clients started together would otherwise stay in phase and hit the ceiling as a group. If you do get a 429, a status read that fails does not end the wait: the run is still executing and still spending, so the helper backs off and polls again.
When should I turn it on?
Use the timeline when a UI shows phases to a human, or while you debug why a long run seems slow. For back-end jobs that only need the final receipt, prefer a run webhook, which removes the poll loop entirely, and keep a plain status poll as backup.
A failed timeline read is also handled gently: it does not end the wait. It is reported through onTransientError and the previous timeline is kept.
- Leave
timelineoff for batch back ends and cron jobs. - Turn it on for user-facing progress on a single run.
- Watch
ratelimit-remainingon responses rather than counting requests. - Never raise the poll rate to compensate; reads are cheap but not free.
Sources
Related posts
More in Developers
- Sume 503: provider_capacity_exceeded vs provider_not_configured
Sume 503s differ: provider_capacity_exceeded: retry later, same key; provider_not_configured is no hard retries, job_ledger_not_configured is an outage
- Sume API errors: a 13-line function that says retry or fix
Map a failed Sume response to out-of-credit, wait, back off, fix the key, retry with the same key, or fix the request, using the documented error envelope.
- GET /v1/jobs/{id} returns 404 for a job your teammate created
A Sume API key reads only jobs its own member created. Jobs made by a teammate or in another workspace return 404 not_found. Why, and how to read them.
- sume/auto for an image series: why to pin a model id instead
sume/auto never tells you which model ran, and job.model stays sume/auto. For a series that must match, send one catalog id such as google/nano-banana-2.
Written by Sume