Workflows are a new feature in Cloudflare’s developer platform. You can use workflows to safely execute a series of steps as defined by code.
Let’s start by creating a new workflow.
Inside the workflows-starter directory, src/index.ts defines two top-level exports: the workflow entrypoint, as well as a default module that handles HTTP requests:
What is a workflow?
A workflow is a class that extends WorkflowEntrypoint. It has access to env, which contains the bindings for the Workers application. It can also accept (typed) parameters used to instantiate the workflow.
A workflow is comprised of steps. You can call step.do to execute a step:
Steps should be awaited, as they are asynchronous. You can return a value from the step, and capture it as a variable:
You can use step.sleep to pause the workflow for a period of time:
The second parameter is a duration-style string, such as '1 minute', '5 seconds', or '1 year'.
All steps are retried by default - see the retry steps section in the docs for more details. You can override the default behavior by passing a retries option to step.do:
Building a custom workflow
So far, we’ve looked at the default code used in Cloudflare’s workflow template. Now, we’ll build our own workflow.
Imagine that we want to build a workflow that fetches analytics for a SaaS product we’re building. It will then take those analytics and report them to a private Slack channel. We can break this down into three steps:
Fetch analytics from our SaaS product
Transform/format those analytics
Report those analytics to a private Slack channel
That workflow can be defined like this:
Although it’s deceptively simple, this workflow as defined is quite powerful. If any step fails, it will retry the workflow using exponential backoff, starting from that step. There’s minimal try/catch style code in this example, yet it still handles errors gracefully.
Calling workflows
Now that we’ve built a workflow, let’s explore how to execute it. In src/index.ts, we can define and export a default module that handles HTTP requests. Inside of that handler function, we can call the workflow by using the create function defined on our workflow:
Where does env.REPORT_ANALYTICS_WORKFLOW come from? It’s defined in wrangler.toml:
By defining the workflow in wrangler.toml, we can access it from our code.
It’s useful to call workflows manually, but we can also call them using a scheduled trigger. For an analytics workflow, we may want to run it every day at a certain time. We can do this by defining a triggers block in wrangler.toml:
With the cron trigger enabled, we can add a new function scheduled to our src/index.ts file:
With the scheduled function defined, the analytics workflow will run every day at 12:00 AM.
Conclusion
I’m quite enjoying playing with Workflows. They’re a great way to reliably execute multi-step code without having to worry about retries, timeouts, or error handling. You can check out the documentation for Workflows to learn more. I also wrote about my indexer project a few days ago, which is built on top of Cloudflare Workflows and is fully open-source.