Skip to content
Saasflare.dev
Get started
Saasflare/tasks
fetch-datacool-downfinalize
every step checkpoints · a dead run resumes here
Tasks

Work that survives the reload.

Long-running jobs on Cloudflare Workflows. Every step checkpoints as it completes, so a run that dies halfway resumes from where it stopped instead of starting the whole thing over.

  • Checkpointed steps
  • Durable sleeps
  • Human approval gates
  • Cron schedules
Why it exists

The job outlives the request.

A Worker request dies in seconds. The work you actually care about — a transcode, a model run, an overnight report — does not fit in that window.

Steps that checkpoint

Each step's result is persisted the moment it finishes. When a run resumes, completed steps replay from storage instead of executing twice — so retrying is cheap and safe.

Sleep without holding anything open

A run can pause and let the platform wake it later. Nothing stays resident, nothing burns CPU while it waits, and the wake-up is exactly once.

Stop and ask a human

A run can block on an external event — an approval, a webhook, a click in your admin — and pick up the instant it arrives.

A run, step by step

Kill it halfway. It comes back.

This is the demo task that ships with the engine: fetch, cool down, finalize. Reload the page mid-run and the completed steps stay completed — they are read back from storage, not re-executed.

demorun_01J8·workflow page reloaded — run continues
  1. fetch-data done
    ctx.step
  2. cool-down done
    ctx.sleep · '2 seconds'
  3. finalize done
    ctx.step

The dashboard mirrors every step, log line and status into D1 and polls for updates.

The dashboard

Every run is a page you can open.

This is the dashboard that ships with the engine, rebuilt here in HTML rather than screenshotted. Task registry on the left, every run and its status on the right — and each run drills down to steps, logs, payload and result.

tasks.saasflare.dev
Saasflare TasksCloudflare Workflows
All runs
Tasks
Demo pipeline 1
Approval gate
Ticker (long-running)
Docs
API Keys
admin@yourco.dev
All runs
Recent runsAllQueuedRunningCompleteErrored
StatusTaskRun IDCreated
runningdemo5b8f0d2e-9a41-4c7b-b1e6-3d92c04a7f157/17/2026, 9:42:07 AM
waitingapprovale2c74d68-0b3f-4b1a-9e57-8a61f9d0c2437/17/2026, 9:40:52 AM
completeticker9f31b7ac-6e05-4d92-8c48-527b0ae14d867/17/2026, 9:40:00 AM
completedemo4a0de91b-7c56-4f38-a2d3-6b18e5c97f027/17/2026, 9:35:11 AM
erroreddemoc67a25f4-3d18-49ab-b590-e01c8f6b2a377/17/2026, 9:31:48 AM
completeapproval1d94e3b0-52c7-46fe-8b2a-90f4d7a6c5187/16/2026, 6:03:29 PM
approvalwaiting Approve Reject Cancel
Created 7/17/2026, 9:40:52 AMStarted 7/17/2026, 9:40:53 AMCompleted —
Steps
preparecompleted
{
  "summary": "Deploy build #42 to production"
}
Logs
9:40:53 AMinfoprepared: Deploy build #42 to production
9:40:53 AMinfoawaiting human approval…

Live, the boring way

The runs table polls every 2 seconds and an open run every 1.5 — no websocket to babysit. Status flips from running to complete while you watch.

A control plane, not a viewer

Cancel a stuck run, retry an errored one, or send a waiting run the event it is blocked on — every run is operable from the buttons in its own header.

Approvals are one click

A run suspended on ctx.waitForApproval shows Approve and Reject right in the header. It costs nothing while it waits; the decision lands and the next line runs.

Defining a task

Steps are just functions you name.

Wrap the parts you never want to repeat in a named step. Sleeps and waits are first-class. Trigger a run over HTTP with a bearer token, from the typed API, or straight across a Worker service binding.

tasks/definitions/demo.ts
defineTask<DemoPayload>('demo', {
  async handler(payload, ctx) {
    const count = payload?.items ?? 3;
    await ctx.log('info', `demo task started for ${count} item(s)`);

    // named step — its result is checkpointed
    const fetched = await ctx.step('fetch-data', async () => ({
      items: Array.from({ length: count }, (_, i) => ({ id: i + 1 })),
    }));

    // durable sleep — nothing stays resident
    await ctx.sleep('cool-down', '2 seconds');

    return ctx.step('finalize', async () => ({
      total: fetched.items.length,
      ok: true,
    }));
  },
});
The details that bite

What the engine actually guarantees.

The boring parts are the ones you find out about at 3am, so here they are up front.

  • Big outputs spill to R2

    A step result over 512 KiB is offloaded to object storage instead of slamming into the engine size limit.

  • Schedules at minute granularity

    A cron trigger sweeps due schedules every minute and starts the runs that are ready.

  • Cancel, retry, resume

    Every run is addressable from the control plane — terminate it, restart it, or send it the event it is waiting for.

  • Progress lands in D1

    Steps, logs and status are mirrored into your database as the run advances, so the timeline survives the worker that produced it.

  • Triggers dedupe on a key

    Send the same trigger twice with one idempotencyKey and you get one run — the key maps to a stable instance id that is created at most once.

  • Retries are per step, with backoff

    Each step declares its own retry limit, delay and backoff curve — constant, linear or exponential — plus a timeout, forwarded straight to the engine.

Cloudflare Workflows · Hono on Workers · D1 for steps and logs · R2 for large outputs · cron-triggered schedules

What it is for

Anything too slow for a request.

AI generation runs

A model call that takes minutes, chained into three more. Checkpoint each stage so a timeout costs you one step, not the whole pipeline.

Media and file processing

Fetch, transcode, upload, notify. Each stage records its own result, and a failed upload never re-runs the transcode.

Scheduled reports

A cron schedule kicks off the run; the run does the slow part on its own time and writes the result when it is ready.

Approval workflows

Do the work, then stop and wait for a human to say yes. The run sits there costing nothing until the event lands.

Tasks is pre-launch. The engine, dashboard and schedules run today, but it ships with demo task definitions and the source is not public yet. Task definitions live inside the server — there is no separate SDK package to install, and the dashboard polls rather than streaming.

SAASFLARE NEWSLETTER

Follow what we’re building.

We’ll only email you when we have a product update or industry news genuinely worth your attention. No inbox noise—only content that’s useful to you.

Product updates and selected industry news. Unsubscribe in one click.