---
title: Workflows is now Generally Available · Changelog
description: Workflows is now GA - ship Workflows that you can rely on in production.
chatbotDeprioritize: true
source_url:
  html: https://developers.cloudflare.com/changelog/2025-04-07-workflows-ga/
  md: https://developers.cloudflare.com/changelog/2025-04-07-workflows-ga/index.md
---

# Changelog

New updates and improvements at Cloudflare.

[Subscribe to RSS](https://developers.cloudflare.com/changelog/rss/index.xml)\
[View all RSS feeds](https://developers.cloudflare.com/fundamentals/new-features/available-rss-feeds/)

![hero image](https://developers.cloudflare.com/_astro/hero.CVYJHPAd_ZEA2nF.svg)

[← Back to all posts](https://developers.cloudflare.com/changelog/)

## Workflows is now Generally Available

Apr 07, 2025

[Workflows ](https://developers.cloudflare.com/workflows/)[Workers](https://developers.cloudflare.com/workers/)

[Workflows](https://developers.cloudflare.com/workflows/) is now *Generally Available* (or "GA"): in short, it's ready for production workloads. Alongside marking Workflows as GA, we've introduced a number of changes during the beta period, including:

* A new `waitForEvent` API that allows a Workflow to wait for an event to occur before continuing execution.
* Increased concurrency: you can [run up to 4,500 Workflow instances](https://developers.cloudflare.com/changelog/2025-02-25-workflows-concurrency-increased/) concurrently — and this will continue to grow.
* Improved observability, including new CPU time metrics that allow you to better understand which Workflow instances are consuming the most resources and/or contributing to your bill.
* Support for `vitest` for testing Workflows locally and in CI/CD pipelines.

Workflows also supports the new [increased CPU limits](https://developers.cloudflare.com/changelog/2025-03-25-higher-cpu-limits/) that apply to Workers, allowing you to run more CPU-intensive tasks (up to 5 minutes of CPU time per instance), not including the time spent waiting on network calls, AI models, or other I/O bound tasks.

#### Human-in-the-loop

The new `step.waitForEvent` API allows a Workflow instance to wait on events and data, enabling human-in-the-the-loop interactions, such as approving or rejecting a request, directly handling webhooks from other systems, or pushing event data to a Workflow while it's running.

Because Workflows are just code, you can conditionally execute code based on the result of a `waitForEvent` call, and/or call `waitForEvent` multiple times in a single Workflow based on what the Workflow needs.

For example, if you wanted to implement a human-in-the-loop approval process, you could use `waitForEvent` to wait for a user to approve or reject a request, and then conditionally execute code based on the result.

* JavaScript

  ```js
  import { Workflow, WorkflowEvent } from "cloudflare:workflows";


  export class MyWorkflow extends WorkflowEntrypoint {
    async run(event, step) {
      // Other steps in your Workflow
      let event = await step.waitForEvent(
        "receive invoice paid webhook from Stripe",
        { type: "stripe-webhook", timeout: "1 hour" },
      );
      // Rest of your Workflow
    }
  }
  ```

* TypeScript

  ```ts
  import { Workflow, WorkflowEvent } from "cloudflare:workflows";


  export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
    async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
      // Other steps in your Workflow
      let event = await step.waitForEvent<IncomingStripeWebhook>("receive invoice paid webhook from Stripe", { type: "stripe-webhook", timeout: "1 hour" })
      // Rest of your Workflow
    }
  }
  ```

You can then send a Workflow an event from an external service via HTTP or from within a Worker using the [Workers API](https://developers.cloudflare.com/workflows/build/workers-api/) for Workflows:

* JavaScript

  ```js
  export default {
    async fetch(req, env) {
      const instanceId = new URL(req.url).searchParams.get("instanceId");
      const webhookPayload = await req.json();


      let instance = await env.MY_WORKFLOW.get(instanceId);
      // Send our event, with `type` matching the event type defined in
      // our step.waitForEvent call
      await instance.sendEvent({
        type: "stripe-webhook",
        payload: webhookPayload,
      });


      return Response.json({
        status: await instance.status(),
      });
    },
  };
  ```

* TypeScript

  ```ts
  export default {
    async fetch(req: Request, env: Env) {
      const instanceId = new URL(req.url).searchParams.get("instanceId")
      const webhookPayload = await req.json<Payload>()


      let instance = await env.MY_WORKFLOW.get(instanceId);
      // Send our event, with `type` matching the event type defined in
      // our step.waitForEvent call
      await instance.sendEvent({type: "stripe-webhook", payload: webhookPayload})


      return Response.json({
        status: await instance.status(),
      });
    },
  };
  ```

Read the [GA announcement blog](https://blog.cloudflare.com/workflows-is-now-generally-available/) to learn more about what landed as part of the Workflows GA.
