Use global concurrency limits to control how many operations run simultaneously, and rate limits to control how frequently operations can start. This guide shows you how to create, manage, and use these limits in your workflows.
For a deeper understanding of how global concurrency limits work and when to use them, see the global concurrency limits concept page.
Manage global concurrency and rate limits
You can create, read, edit, and delete concurrency limits through the Prefect UI, CLI, Python SDK, Terraform, or API.
When creating a concurrency limit, you can specify:
- Name: How you’ll reference the limit in your code (no special characters like
/, %, &, >, <)
- Concurrency Limit: Maximum number of slots available
- Slot Decay Per Second: Rate at which slots are released (required for rate limiting)
- Active: Whether the limit is enforced (
true) or disabled (false)
Using the UI
Navigate to the Concurrency section in the Prefect UI to create, update, and delete concurrency limits.
Using the CLI
Create a new concurrency limit with the prefect gcl create command:
Inspect a concurrency limit:
Update a concurrency limit:
Delete a concurrency limit:
See all available commands and options with prefect gcl --help.
Using the API
Use the concurrency context manager
Control concurrent operations using the concurrency context manager. Choose the synchronous or asynchronous version based on your code.
By default, if a concurrency limit doesn’t exist or lease renewal fails, a warning is logged but execution continues.Use strict=True to raise an error instead. This ensures concurrency enforcement is guaranteed, useful for preventing resource exhaustion like database connection pool limits.Use raise_on_lease_renewal_failure=False to allow long-running tasks to tolerate transient lease renewal errors even when strict=True is set.
Synchronous usage
Asynchronous usage
In both examples, the concurrency context manager occupies one slot on the database concurrency limit. If no slots are available, execution blocks until a slot becomes available.
Using strict mode
Enable strict mode to ensure errors are raised if the limit doesn’t exist or if lease renewal fails:
Use raise_on_lease_renewal_failure to control lease renewal behavior independently of strict. For example, use strict=True to require the limit exists at acquisition time, while allowing long-running tasks to continue through transient renewal errors:
Use rate_limit
Control the frequency of operations using the rate_limit function.
The concurrency limit must have slot_decay_per_second configured. Without it, rate_limit will fail.
Synchronous usage
Asynchronous usage
The rate_limit function ensures requests are made at a controlled pace based on the concurrency limit’s slot_decay_per_second setting.
Use outside of flows
You can use concurrency and rate_limit in any Python code, not just within flows.
Common patterns
Throttle task submission
Prevent overwhelming downstream systems by controlling how quickly tasks are submitted:
Limit database connections
Prevent exhausting your database connection pool by limiting concurrent queries:
Control parallel processing
Process data in controlled batches to avoid resource exhaustion:
Next steps
For more information about how global concurrency limits work and when to use them versus other concurrency controls, see the global concurrency limits concept page.