Trigger Workflows·续
index.jsjs
export class MyWorkflow extends WorkflowEntrypoint {
async run(event, step) {
const listResult = await step.do("list files from R2", async () => {
// Restarts delete all state with the exception of search params.
// So we will need a cursor to keep track of progress.
const maybeCursor = await this.env.CHUNKS_BUCKET.get(
`cursor/${event.instanceId}`,
);
const cursor = maybeCursor
? (await maybeCursor.json()).cursor
: undefined;
// List first 100 files from R2 with prefix "chunked/"
const listed = await this.env.CHUNKS_BUCKET.list({
prefix: "chunked/",
limit: 100,
cursor,
});
if (listed.truncated) {
const cursor = listed.cursor;
await this.env.CHUNKS_BUCKET.put(
`cursor/${event.instanceId}`,
JSON.stringify({ cursor }),
{
httpMetadata: {
contentType: "application/json",
},
},
);
}
return {
keys: listed.objects.map((obj) => obj.key),
truncated: listed.truncated,
};
});
for (const key of listResult.keys) {
await step.do(`process file: ${key}`, async () => {
return await doSomething(key, this.env.CHUNKS_BUCKET, event.instanceId);
});
}
await step.do("restart workflow", async () => {
if (listResult.truncated) {
// There are still chunks to process, restarting the workflow to continue processing.
const instance = await this.env.CHUNK_PROCESSOR.get(event.instanceId);
await instance.restart();
} else {
// If the workflow has ended we reset the cursor, so that we can preserve determinism.
// If/when we re-run this workflow we will still process all the files.
await this.env.CHUNKS_BUCKET.delete(`cursor/${event.instanceId}`);
return "was not truncated, done";
}
});
}
}
index.tsts
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
const listResult = await step.do("list files from R2", async () => {
// Restarts delete all state with the exception of search params.
// So we will need a cursor to keep track of progress.
const maybeCursor = await this.env.CHUNKS_BUCKET.get(
`cursor/${event.instanceId}`,
);
const cursor = maybeCursor
? (await maybeCursor.json<{ cursor: string }>()).cursor
: undefined;
// List first 100 files from R2 with prefix "chunked/"
const listed = await this.env.CHUNKS_BUCKET.list({
prefix: "chunked/",
limit: 100,
cursor,
});
if (listed.truncated) {
const cursor = listed.cursor;
await this.env.CHUNKS_BUCKET.put(
`cursor/${event.instanceId}`,
JSON.stringify({ cursor }),
{
httpMetadata: {
contentType: "application/json",
},
},
);
}
return {
keys: listed.objects.map((obj) => obj.key),
truncated: listed.truncated,
};
});
for (const key of listResult.keys) {
await step.do(`process file: ${key}`, async () => {
return await doSomething(key, this.env.CHUNKS_BUCKET, event.instanceId);
});
}
await step.do("restart workflow", async () => {
if (listResult.truncated) {
// There are still chunks to process, restarting the workflow to continue processing.
const instance = await this.env.CHUNK_PROCESSOR.get(event.instanceId);
await instance.restart();
} else {
// If the workflow has ended we reset the cursor, so that we can preserve determinism.
// If/when we re-run this workflow we will still process all the files.
await this.env.CHUNKS_BUCKET.delete(`cursor/${event.instanceId}`);
return "was not truncated, done";
}
});
}
}
Delete Workflow instances
Deleting an instance removes its stored state. Deleting a running instance stops its current execution without running rollback handlers.
Delete one instance by calling delete() on its handle:
const instance = await env.MY_WORKFLOW.get("instance-abc");
await instance.delete();
const instance = await env.MY_WORKFLOW.get("instance-abc");
await instance.delete();
If a Workflow deletes its own instance, execution stops during await instance.delete(). Code after the call does not run.
Delete up to 100 instances in one call with deleteBatch():
const result = await env.MY_WORKFLOW.deleteBatch([
"instance-abc",
"instance-def",
]);
console.log(result.deleted); // [{ id: "instance-abc" }, { id: "instance-def" }]
console.log(result.errors); // Per-instance failures, if any
const result = await env.MY_WORKFLOW.deleteBatch([
"instance-abc",
"instance-def",
]);
console.log(result.deleted); // [{ id: "instance-abc" }, { id: "instance-def" }]
console.log(result.errors); // Per-instance failures, if any
deleteBatch() accepts between 1 and 100 IDs. Missing IDs are returned as per-instance errors. Duplicate IDs count toward the limit and are deleted once, with the result repeated for each input position. If any ID is invalid, the call fails before deleting any instances.
Wrangler accepts one or more instance IDs or a file containing a top-level JSON array of strings. You can combine positional IDs with --filename, up to 100 IDs total. Use latest to delete the most recently created instance.
instance-ids.jsonjson
["instance-abc", "instance-def"]
npx wrangler workflows instances delete <WORKFLOW_NAME> <INSTANCE_ID>
npx wrangler workflows instances delete <WORKFLOW_NAME> <INSTANCE_ID> <INSTANCE_ID>
npx wrangler workflows instances delete <WORKFLOW_NAME> latest
npx wrangler workflows instances delete <WORKFLOW_NAME> --filename ./instance-ids.json
# For local Workflow instances during wrangler dev:
npx wrangler workflows instances delete <WORKFLOW_NAME> <INSTANCE_ID> --local
For the full APIs, refer to delete and deleteBatch.
Trigger a Workflow from another Workflow
You can create a new Workflow instance from within a step of another Workflow. The parent Workflow will not block waiting for the child Workflow to complete — it continues execution immediately after the child instance is successfully created.
export class ParentWorkflow extends WorkflowEntrypoint {
async run(event, step) {
// Perform initial work
const result = await step.do("initial processing", async () => {
// ... processing logic
return { fileKey: "output.pdf" };
});
// Trigger a child workflow for additional processing
const childInstance = await step.do("trigger child workflow", async () => {
return await this.env.CHILD_WORKFLOW.create({
id: `child-${event.instanceId}`,
params: { fileKey: result.fileKey },
});
});
// Parent continues immediately - not blocked by child workflow
await step.do("continue with other work", async () => {
console.log(`Started child workflow: ${childInstance.id}`);
// This runs right away, regardless of child workflow status
});
}
}
export class ParentWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// Perform initial work
const result = await step.do("initial processing", async () => {
// ... processing logic
return { fileKey: "output.pdf" };
});
// Trigger a child workflow for additional processing
const childInstance = await step.do("trigger child workflow", async () => {
return await this.env.CHILD_WORKFLOW.create({
id: `child-${event.instanceId}`,
params: { fileKey: result.fileKey },
});
});
// Parent continues immediately - not blocked by child workflow
await step.do("continue with other work", async () => {
console.log(`Started child workflow: ${childInstance.id}`);
// This runs right away, regardless of child workflow status
});
}
}
If the child Workflow fails to start, the step will fail and be retried according to your retry configuration. Once the child instance is successfully created, it runs independently from the parent.
REST API (HTTP)
Refer to the Workflows REST API documentation.
Command line (CLI)
Refer to the CLI quick start to learn more about how to manage and trigger Workflows via the command-line.
Was this helpful?
YesNo
On this page
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/workflows/build/trigger-workflows/#page","headline":"Trigger Workflows","description":"Trigger Workflows from Workers bindings, the REST API, or the Wrangler CLI.","url":"https://developers.cloudflare.com/workflows/build/trigger-workflows/","inLanguage":"en","image":"https://developers.cloudflare.com/workflows/build/trigger-workflows/og.png?v=48434d0a23d3b226","dateModified":"2026-10-15","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["Bindings"]}
description: View a visual diagram of your Workflow steps, conditionals, and parallel logic in the Cloudflare dashboard. title: Visualize Workflows image: https://developers.cloudflare.com/workflows/build/visualizer/og.png?v=9d24883e3b757bc3
Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/workflows/llms.txt
Use this file to discover all available pages before exploring further.
Docs