Cloudflare Workflows: sleep and poll a Sume run, no open request
A Cloudflare Workflow can submit a Sume run, step.sleep for minutes, then check status again. Here are the step limits that bound how long you can poll.

A Cloudflare Workflow lets you submit a Sume run in one step.do, wait with step.sleep, and check the status in another step.do, without any request held open. Sleeping instances do not use concurrency slots, and the longest sleep is 365 days, so the real limit is the step count: 1,024 on the Free plan. Poll at a sensible interval and you will not reach it.
The Cloudflare facts are from Workflows get started and Workflows limits, both read 2026-10-10. The Sume facts are from Runs and results and Create a run.
Which limits shape the design?
The limits page gives the numbers below. A step result that is not a stream may be at most 1 MiB, so store a run id and a status, never the finished media. Each step has a compute time budget, which is small on Free. The retained state of finished instances is also short.
Retention matters for audits. Finished instances keep their state for 3 days on Free and 30 days on Paid, so write the run id and the final status to your own storage if you need a longer record. Sume keeps the receipt on its side, which you can read again by run id.
| Limit | Free | Paid |
|---|---|---|
| Steps per workflow | 1,024 | 10,000 default, 25,000 maximum |
| Compute time per step | 10 ms | 30 s default, 5 min maximum |
| Concurrent instances | 100 | 50,000 |
| Completed-instance state kept | 3 days | 30 days |
| Largest non-stream step result | 1 MiB | 1 MiB |
| Longest sleep | 365 days | 365 days |
How many polls fit?
A poll loop of one step.do and one step.sleep per round uses 2 steps. With a submit step and a final step, a Free instance has 1,024 minus 2 = 1,022 steps left, which is 511 rounds. Sume's own ceiling is lower: Runs and results says a run is force-finalized as failed 90 minutes after creation, so polling once a minute needs at most about 90 rounds, or 180 steps. The step budget is not the problem; the interval is.
Waiting does not cost the compute time budget either, because the 10 ms Free limit applies to the work inside a step, not the sleeping between steps. The fetch inside a step is network wait, so confirm your own measurements on your own plan.
import { WorkflowEntrypoint } from "cloudflare:workers";
export class RenderFlow extends WorkflowEntrypoint {
async run(event, step) {
const H = { Authorization: `Bearer ${this.env.SUME_API_KEY}`, "Content-Type": "application/json" };
const id = await step.do("submit", async () => {
const r = await fetch("https://api.sume.com/v1/formats/acme/promo/runs", {
method: "POST", headers: { ...H, "Idempotency-Key": `cf-${event.instanceId}` },
body: JSON.stringify({ instruction: "Make the promo.", input: event.payload })
});
return (await r.json()).data.id;
});
for (let i = 0; i < 95; i++) {
await step.sleep(`wait-${i}`, "1 minute");
const s = await step.do(`poll-${i}`, async () => {
const r = await fetch(`https://api.sume.com/v1/format-runs/${id}/status`, { headers: H });
return (await r.json()).data.status;
});
if (s !== "queued" && s !== "processing") return { id, status: s };
}
return { id, status: "timeout" };
}
}What does the loop need to get right?
Step names must be unique per round, which is why the index is in the name. The idempotency key uses the instance id, so a retried submit step returns the original run through idempotency_hit: true. The statuses queued and processing come from the Sume runs page; treat everything else as an end state and read it from the status payload instead of guessing.
After the loop, a final step should fetch GET /v1/format-runs/{run_id}/result. It answers 409 run_not_completed until the run is terminal, so reaching it early is harmless.
Use an exponential interval instead of a fixed minute if the Format is short. Sume's own example sleeps with a doubling interval capped at 60 seconds, which finds fast runs quickly without spending steps on slow ones.
Should I wait for an event instead?
The get started guide also shows step.waitForEvent, which suspends the workflow until something sends it an event. Pair it with a communication.webhook_url on the Sume run: a Worker receives the format.run.terminal webhook, verifies the signature and sends the event to the instance. You then poll only as a fallback.
Choose the plain sleep loop when you want the fewest moving parts, and the event wait when the render is long and you would rather wake once.
Sources
Related posts
More in Integrations
- Codex default_tools_approval_mode = writes for Sume MCP
Codex sets approval per MCP server and per tool. Which of auto, prompt, writes and approve suits Sume's read and paid tools, and what output_token_limit does.
- Cursor remote MCP has no envFile: where the Sume key goes
Cursor's envFile works for stdio servers only. For Sume's remote MCP, read the key from your shell with a headers entry, or skip keys and use OAuth.
- Docker Agent YAML: add Sume as a remote MCP toolset
Docker Agent takes a remote MCP URL, headers and a tools allowlist. Here is the Sume entry with a Bearer key from the environment and a read-only tool list.
- Framer looping video: keep it under 5 MB, Framer won't compress
Framer says keep looping videos under 5 MB, uses H.264 MP4, and serves a 4K upload at full size. Render and trim a Sume clip small before you upload.
Written by Sume