Back to all docs

Concurrency

Concurrency

Introduction

Sometimes you may need to execute several slow tasks which do not depend on one another. In many cases, significant performance improvements can be realized by executing the tasks concurrently. Laravel’s Concurrency facade provides a simple, convenient API for executing closures concurrently.

How it Works

Laravel achieves concurrency by serializing the given closures and dispatching them to a hidden Artisan CLI command, which unserializes the closures and invokes it within its own PHP process. After the closure has been invoked, the resulting value is serialized back to the parent process.

The Concurrency facade supports three drivers: process (the default), fork, and sync.

The fork driver offers improved performance compared to the default process driver, but it may only be used within PHP’s CLI context, as PHP does not support forking during web requests. Before using the fork driver, you need to install the laravelcompany/fork package:

composer require laravelcompany/fork

The sync driver is primarily useful during testing when you want to disable all concurrency and simply execute the given closures in sequence within the parent process.

Running Concurrent Tasks

To run concurrent tasks, you may invoke the Concurrency facade’s run method. The run method accepts an array of closures which should be executed simultaneously in child PHP processes:

use Illuminate\Support\Facades\Concurrency;
use Illuminate\Support\Facades\DB;

[$userCount, $orderCount] = Concurrency::run([
    fn () => DB::table('users')->count(),
    fn () => DB::table('orders')->count(),
]);

To use a specific driver, you may use the driver method:

$results = Concurrency::driver('fork')->run(...);

Or, to change the default concurrency driver, you should publish the concurrency configuration file via the config:publish Artisan command and update the default option within the file:

php artisan config:publish concurrency

Deferring Concurrent Tasks

If you would like to execute an array of closures concurrently, but are not interested in the results returned by those closures, you should consider using the defer method. When the defer method is invoked, the given closures are not executed immediately. Instead, Laravel will execute the closures concurrently after the HTTP response has been sent to the user:

use App\Services\Metrics;
use Illuminate\Support\Facades\Concurrency;

Concurrency::defer([
    fn () => Metrics::report('users'),
    fn () => Metrics::report('orders'),
]);

More Documentation

- ## Prologue AI Assisted Development Artisan Console Asset Bundling (Vite) Authentication Authorization Blade Templates Broadcasting Cache Collections Configuration Console Tests Context Contracts Contribution Guide Controllers CSRF Protection Database Testing Database: Getting Started Database: Migrations Database: Pagination Database: Query Builder Database: Seeding Deployment Directory Structure Eloquent: API Resources Eloquent: Collections Eloquent: Factories Eloquent: Getting Started Eloquent: Mutators & Casting Eloquent: Relationships Eloquent: Serialization Email Verification Encryption Error Handling Events Facades File Storage Frontend Hashing Helpers HTTP Client HTTP Requests HTTP Responses HTTP Session HTTP Tests Installation Laravel AI SDK Laravel Boost Laravel Cashier (Paddle) Laravel Cashier (Stripe) Laravel Dusk Laravel Envoy Laravel Folio Laravel Fortify Laravel Homestead Laravel Horizon Laravel MCP Laravel Mix Laravel Octane Laravel Passport Laravel Pennant Laravel Pint Laravel Pulse Laravel Reverb Laravel Sail Laravel Sanctum Laravel Scout Laravel Socialite Laravel Telescope Laravel Valet Localization Logging Mail Middleware Mocking MongoDB Notifications Package Development Precognition Processes Prompts Queues Rate Limiting Redis Release Notes Request Lifecycle Resetting Passwords Routing Search Service Container Service Providers Starter Kits Strings Task Scheduling Testing: Getting Started The MIT License (MIT) Upgrade Guide URL Generation Validation Views