What is concurrency
If you execute multiple independent operations—such as requests to several external APIs or database aggregations—sequentially, the total time is the sum of each operation. If you execute them concurrently, the total time is reduced to about the time of the single slowest operation. Laravel’sConcurrency facade provides a simple API for exactly this kind of concurrent execution.
The
Concurrency facade was introduced in Laravel 11 and continues to be available in Laravel 13.
The default driver uses child PHP processes, so it works without any additional packages.How it works
TheConcurrency facade serializes the closures you pass in, sends them to a hidden Artisan command, and runs each one as a separate PHP process.
When each operation completes, the return value is serialized back to the parent process.
Three drivers are available.
Basic usage
Concurrency::run()
If you pass an array of closures to therun() method, they are executed concurrently.
The return value is an array of each closure’s return values.
Specifying a driver
To use a specific driver, use thedriver() method.
default option.
Using the fork driver
Thefork driver is faster than the process driver, but it only works in a PHP CLI environment (Artisan commands or queue workers).
It cannot be used during a web request.
Before using it, install the spatie/fork package.
Not caring about the return value: Concurrency::defer()
If you aren’t interested in the results and want the operation to run in the background after the HTTP response has been returned, use thedefer() method.
defer().
They run concurrently after the HTTP response has been sent to the user.
Practical example: calling multiple external APIs concurrently
Consider a dashboard for an e-commerce site that fetches information from three APIs: inventory management, sales aggregation, and shipping status.Sequential execution (before)
Concurrent execution (after)
Running multiple database aggregations concurrently
Configuration for testing
In your test environment, using thesync driver runs closures sequentially.
There is no process-startup overhead from concurrency, so tests run faster.
.env.testing.
Caveats
Closure limitations
Closure limitations
Closures are serialized and passed to child processes.
You cannot capture unserializable objects (such as database connections, file handles, or resources) from the enclosing scope.
Recreate the objects you need inside the closure.
process driver overhead
process driver overhead
The
process driver has a child-process startup cost, so for very short operations (a few milliseconds or less), concurrent execution may not be faster.
It shines when parallelizing operations that take at least 100ms, such as HTTP requests or database aggregations.fork driver limitations
fork driver limitations
The
fork driver forks the PHP process, so it cannot be used during web requests (FPM or Apache).
Only use it inside Artisan commands or queue workers.Exception handling
Exception handling
If an exception occurs during concurrent execution,
run() re-throws the exception.
If you want the other operations to continue when an individual operation raises, use try/catch inside the closure.Next steps
Queues and jobs
Learn how to run operations asynchronously in the background with queues and jobs.