Jump to Content
Application Development

Buffer workflow executions with a Cloud Tasks queue

July 11, 2023
Mete Atamel

Cloud Developer Advocate

Introduction

In my previous post, I talked about how you can use a parent workflow to execute child workflows in parallel for faster overall processing time and easier detection of errors. Another useful pattern is to use a Cloud Tasks queue to create Workflows executions and that’s the topic of this post.

When your application experiences a sudden surge of traffic, it's natural to want to handle the increased load by creating a high number of concurrent workflow executions. However, Google Cloud’s Workflows enforces quotas to prevent abuse and ensure fair resource allocation. These quotas limit the maximum number of concurrent workflow executions per region, per project, for example, Workflows currently enforces a maximum of 2000 concurrent executions by default. Once this limit is reached, any new executions beyond the quota will fail with an HTTP 429 error.

A Cloud Tasks queue can help. Rather than creating Workflow executions directly, you can add Workflows execution tasks to the Cloud Tasks queue and let Cloud Tasks drain the queue at a rate that you define. This allows for better utilization of your workflow quota and ensures the smooth execution of workflows.

https://storage.googleapis.com/gweb-cloudblog-publish/images/0_workflows_with_queue.max-1300x1300.png

Let's dive into how to set this up. 

Create a Cloud Tasks queue

We'll start by creating a Cloud Tasks queue. The Cloud Tasks queue acts as a buffer between the parent workflow and the child workflows, allowing us to regulate the rate of executions.

Create the Cloud Tasks queue (initially with no dispatch rate limits) with the desired name and location:

Loading...

Now that we have our queue in place, let's proceed to set up the child workflow.

Create and deploy a child workflow

The child workflow performs a specific task and returns a result to the parent workflow.

Create workflow-child.yaml to define the child workflow:

Loading...

In this example, the child workflow receives an iteration argument from the parent workflow, simulates work by waiting for 10 seconds, and returns a string as the result.

Deploy the child workflow:

Loading...

Create and deploy a parent workflow

Next, create a parent workflow in workflow-parent.yaml.

The workflow assigns some constants first. Note that it's referring to the child workflow and the queue name between the parent and child workflows:

Loading...

In the next step, Workflows creates and adds a high number of tasks (whose body is an HTTP request to execute the child workflow) to the Cloud Tasks queue:

Loading...

Note that task creation is a non-blocking call in Workflows. Cloud Tasks takes care of running those tasks to execute child workflows asynchronously.

Deploy the parent workflow:

Loading...

Execute the parent workflow with no dispatch rate limits

Time to execute the parent workflow:

Loading...

As the parent workflow is running, you can see parallel executions of the child workflow, all executed roughly around the same:

https://storage.googleapis.com/gweb-cloudblog-publish/images/1_parallel_executions_allsametime.max-1000x1000.png

In this case, 100 executions is a well under the concurrency limit for Workflows. Quota issues may arise if you submit 1000s of executions all at once. This is when Cloud Tasks queue and its rate limits become useful.

Execute the parent workflow with dispatch rate limits

Let's now apply a rate limit to the Cloud Tasks queue. In this case, 1 dispatch per second:

Loading...

Execute the parent workflow again:

Loading...

This time, you see a more smooth execution rate (1 execution request per second):

https://storage.googleapis.com/gweb-cloudblog-publish/images/2_parallel_executions_buffered.max-900x900.png

Summary

By introducing a Cloud Tasks queue before executing a workflow and playing with different dispatch rates and concurrency settings, you can better utilize your Workflows quota and stay below the limits without triggering unnecessary quota related failures. 

Check out the Buffer HTTP requests with Cloud Tasks codelab, if you want to get more hands-on experience with Cloud Tasks. As always, feel free to contact me on Twitter @meteatamel for any questions or feedback.

Posted in