Trigger Workflows

Last updated Oct 15, 2026 You can trigger Workflows both programmatically and via the Workflows APIs, including:

  1. With Workers via HTTP requests in a fetch handler, or bindings from a queue or scheduled handler
  2. On a recurring interval by defining schedules on a Workflow binding in your Wrangler configuration
  3. Using the Workflows REST API
  4. Via the wrangler CLI in your terminal

Workers API (Bindings)

You can interact with Workflows programmatically from any Worker script by creating a binding to a Workflow. A Worker can bind to multiple Workflows, including Workflows defined in other Workers projects (scripts) within your account.

You can trigger a Workflow:

  • Directly over HTTP via the fetch handler
  • From a Queue consumer inside a queue handler
  • On a recurring schedule by defining schedules on the Workflow binding in wrangler.jsonc
  • From a Cron Trigger inside a scheduled handler
  • Within a Durable Object

Note

New to Workflows? Start with the Workflows tutorial to deploy your first Workflow and familiarize yourself with Workflows concepts.

To bind to a Workflow from your Workers code, you need to define a binding to a specific Workflow. For example, to bind to the Workflow defined in the get started guide, you would configure the Wrangler configuration file with the below:

{
    "$schema": "./node_modules/wrangler/config-schema.json",
    "name": "workflows-tutorial",
    "main": "src/index.ts",
    "upload_source_maps": true,
    // Set this to today's date
    "compatibility_date": "2026-10-27",
    "workflows": [
        {
            // The name of the Workflow
            "name": "workflows-tutorial",
            // The binding name, which must be a valid JavaScript variable name.  This will
            // be how you call (run) your Workflow from your other Workers handlers or
            // scripts.
            "binding": "MY_WORKFLOW",
            // Must match the class defined in your code that extends the Workflow class
            "class_name": "MyWorkflow"
        }
    ]
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "workflows-tutorial"
main = "src/index.ts"
upload_source_maps = true
# Set this to today's date
compatibility_date = "2026-10-27"

[[workflows]]
name = "workflows-tutorial"
binding = "MY_WORKFLOW"
class_name = "MyWorkflow"

The binding = "MY_WORKFLOW" line defines the JavaScript variable that our Workflow methods are accessible on, including create (which triggers a new instance) or get (which returns the status of an existing instance).

Schedule a Workflow directly

If you want to create Workflow instances on a recurring interval, add a schedules array (up to 100 cron expressions per account) to the Workflow binding in your Wrangler configuration:

{
    "$schema": "./node_modules/wrangler/config-schema.json",
    "name": "workflows-tutorial",
    "main": "src/index.ts",
    "upload_source_maps": true,
    // Set this to today's date
    "compatibility_date": "2026-10-27",
    "workflows": [
        {
            "name": "workflows-tutorial",
            "binding": "MY_WORKFLOW",
            "class_name": "MyWorkflow",
            "schedules": ["0 * * * *"]
        }
    ]
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "workflows-tutorial"
main = "src/index.ts"
upload_source_maps = true
# Set this to today's date
compatibility_date = "2026-10-27"

[[workflows]]
name = "workflows-tutorial"
binding = "MY_WORKFLOW"
class_name = "MyWorkflow"
schedules = [ "0 * * * *" ]

Each matching cron expression creates a new Workflow instance automatically. Use this when you want to run a Workflow on a schedule without defining top-level triggers.crons and a separate scheduled handler.

Scheduled instances include the matching cron expression and scheduled trigger time on event.schedule:

export class MyWorkflow extends WorkflowEntrypoint<Env> {
    async run(event: WorkflowEvent<unknown>, step: WorkflowStep) {
        if (event.schedule) {
            console.log(event.schedule.cron);
            console.log(new Date(event.schedule.scheduledTime));
        }
    }
}

On Workers Paid, Workflow instances created by schedules can run for up to one hour per cron firing without consuming a Workflow concurrency slot. If the instance pauses or sleeps after that window, the instance yields and enters the normal concurrency queue upon resume. It resumes when a concurrency slot is available.

Use the latest Wrangler release when configuring Workflow schedules. If your local Wrangler schema does not recognize schedules yet, update Wrangler before deploying.

The following example shows how you can manage Workflows from within a Worker, including:

  • Retrieving the status of an existing Workflow instance by its ID
  • Creating (triggering) a new Workflow instance
  • Returning the status of a given instance ID

src/index.tsts

interface Env {
    MY_WORKFLOW: Workflow;
}

export default {
    async fetch(req: Request, env: Env) {
        // Get instanceId from query parameters
        const instanceId = new URL(req.url).searchParams.get("instanceId");

// If an ?instanceId=<id> query parameter is provided, fetch the status
        // of an existing Workflow by its ID.
        if (instanceId) {
            let instance = await env.MY_WORKFLOW.get(instanceId);
            return Response.json({
                status: await instance.status(),
            });
        }

// Else, create a new instance of our Workflow, passing in any (optional)
        // params and return the ID.
        const newId = crypto.randomUUID();
        let instance = await env.MY_WORKFLOW.create({ id: newId });
        return Response.json({
            id: instance.id,
            details: await instance.status(),
        });
    },
};

Inspect a Workflow's status

You can inspect the status of any running Workflow instance by calling status against a specific instance ID. This allows you to programmatically inspect whether an instance is queued (waiting to be scheduled), actively running, paused, or errored.

let instance = await env.MY_WORKFLOW.get("abc-123");
let status = await instance.status(); // Returns an InstanceStatus

The possible values of status are as follows:

  status:
    | "queued" // means that instance is waiting to be started (see concurrency limits)
    | "running"
    | "paused"
    | "errored"
    | "terminated" // user terminated the instance while it was running
    | "complete"
    | "waiting" // instance is hibernating and waiting for sleep or event to finish
    | "waitingForPause" // instance is finishing the current work to pause
    | "unknown";
  error?: {
    name: string,
    message: string
  };
    output?: unknown;
    rollback:
        | {
                outcome: "complete" | "failed";
                error: {
                    name: string,
                    message: string,
                } | null,
          }
        | null;

If your Workflow registers rollback handlers on step.do(), inspect rollback after the instance finishes to see whether the compensating steps completed successfully. While rollback is actively running, the Workers API continues to return status: "running".

To receive historical and live execution updates without polling, refer to Subscribe to events.

Explicitly pause a Workflow

You can explicitly pause a Workflow instance (and later resume it) by calling pause against a specific instance ID.

let instance = await env.MY_WORKFLOW.get("abc-123");
await instance.pause(); // Returns Promise<void>

Resume a Workflow

You can resume a paused Workflow instance by calling resume against a specific instance ID.

let instance = await env.MY_WORKFLOW.get("abc-123");
await instance.resume(); // Returns Promise<void>

Calling resume on an instance that is not currently paused will have no effect.

Caution

If you have reached the maximum concurrent instances for your Workflow, resuming an instance may not restart it immediately. The instance will be queued until a concurrency slot becomes available.

Stop a Workflow

You can stop/terminate a Workflow instance by calling terminate against a specific instance ID.

let instance = await env.MY_WORKFLOW.get("abc-123");
await instance.terminate(); // Returns Promise<void>

To run registered rollback handlers before terminating, pass rollback: true:

let instance = await env.MY_WORKFLOW.get("abc-123");
await instance.terminate({ rollback: true }); // Returns Promise<void>

You can also run rollback handlers from Wrangler:

npx wrangler workflows instances terminate <WORKFLOW_NAME> <INSTANCE_ID> --rollback
# For a local Workflows instance during wrangler dev:
npx wrangler workflows instances terminate <WORKFLOW_NAME> <INSTANCE_ID> --local --rollback

Once stopped/terminated, the Workflow instance cannot be resumed.

Restart a Workflow

let instance = await env.MY_WORKFLOW.get("abc-123");
await instance.restart(); // Returns Promise<void>

Restarting an instance will immediately cancel any in-progress steps, erase any intermediate state, and treat the Workflow as if it was run for the first time. However, the restarted instance maintains the concurrency slot of the previous instance instead of returning to the queued state.

Caution

Exercise caution when using the restart() method to avoid concurrency slot deprivation. If you call the restart() method recursively without a conditional, that instance will run indefinitely, effectively eliminating a concurrency slot.

To restart an instance from a specific step instead of the beginning, refer to restart in the Workers API reference.

Because a restart erases all intermediate state, keep any state that must survive a restart outside of the instance itself. The following example uses the restart method to maintain a document processing pipeline:

  • Chunks of a document are stored in, and retrieved from, R2 with an identifiable object prefix.
  • Each R2 object key is used as the instanceId for processing that chunk.
  • The workflow retrieves 100 chunks at a time, processes the chunks, and updates their prefix.
  • Then, if there are remaining objects with the original prefix, the Workflow instance restarts.