Laravel Concurrency Facade &amp; Process Pools | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com) [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles  ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

  [ home ](https://www.msaied.com)    [ articles ](https://www.msaied.com/articles)    Laravel Concurrency Facade and Process Pools for Parallel Work        On this page       1. [  Why Parallelism Matters in a Synchronous PHP World ](#why-parallelism-matters-in-a-synchronous-php-world)
2. [  The Concurrency Facade ](#the-concurrency-facade)
3. [  Choosing a Driver ](#choosing-a-driver)
4. [  What Concurrency Is Not ](#what-concurrency-is-not)
5. [  Process Pools for Heavier Parallelism ](#process-pools-for-heavier-parallelism)
6. [  Concurrency vs Process Pool — Decision Matrix ](#concurrency-vs-process-pool-decision-matrix)
7. [  Avoiding Shared-State Bugs ](#avoiding-shared-state-bugs)
8. [  Practical Pattern: Parallel Dashboard Aggregates ](#practical-pattern-parallel-dashboard-aggregates)
9. [  Key Takeaways ](#key-takeaways)

  ![Laravel Concurrency Facade and Process Pools for Parallel Work](https://cdn.msaied.com/332/49731d56ab868b7afcf2fc19cc97aab8.png)

  #laravel   #concurrency   #process-pools   #performance  

 Laravel Concurrency Facade and Process Pools for Parallel Work 
================================================================

     30 Jun 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

  9 sections  

1. [  01   Why Parallelism Matters in a Synchronous PHP World  ](#why-parallelism-matters-in-a-synchronous-php-world)
2. [  02   The Concurrency Facade  ](#the-concurrency-facade)
3. [  03   Choosing a Driver  ](#choosing-a-driver)
4. [  04   What Concurrency Is Not  ](#what-concurrency-is-not)
5. [  05   Process Pools for Heavier Parallelism  ](#process-pools-for-heavier-parallelism)
6. [  06   Concurrency vs Process Pool — Decision Matrix  ](#concurrency-vs-process-pool-decision-matrix)
7. [  07   Avoiding Shared-State Bugs  ](#avoiding-shared-state-bugs)
8. [  08   Practical Pattern: Parallel Dashboard Aggregates  ](#practical-pattern-parallel-dashboard-aggregates)
9. [  09   Key Takeaways  ](#key-takeaways)

       Why Parallelism Matters in a Synchronous PHP World
--------------------------------------------------

PHP runs one request at a time per worker, but that doesn't mean every task inside a request must be sequential. Laravel ships two distinct primitives for parallelism: the `Concurrency` facade (introduced in Laravel 11) and the `Process` facade's pool API. Knowing which to reach for — and where each one breaks — separates a senior engineer from someone who just throws everything onto a queue.

---

The Concurrency Facade
----------------------

The `Concurrency` facade executes an array of closures in parallel by forking child processes under the hood (via `spatie/fork` or the built-in driver). Each closure runs in an isolated process, so there is **no shared memory** between them.

```php
use Illuminate\Support\Facades\Concurrency;

[$orders, $inventory, $pricing] = Concurrency::run([
    fn () => Order::where('user_id', $userId)->count(),
    fn () => Inventory::lowStock()->get(),
    fn () => PricingService::currentRates(),
]);

```

The return value is an array of results in the same order as the input. Exceptions in any child bubble up as a `Throwable` on the corresponding index — wrap individual closures if you need fault isolation.

### Choosing a Driver

Laravel ships two drivers:

- **`fork`** — uses `pcntl_fork`. Fast, zero overhead, but unavailable on Windows and inside FrankenPHP workers where forking is unsafe.
- **`process`** — spawns a fresh `php artisan` subprocess per closure. Slower startup, but works everywhere and respects `.env` bootstrapping cleanly.

Set the driver in `config/concurrency.php` or per-call:

```php
Concurrency::driver('process')->run([...]);

```

### What Concurrency Is Not

The `Concurrency` facade is **not** a queue. It blocks the current request until all children finish. Use it for fan-out reads that would otherwise be sequential — not for fire-and-forget work or tasks that take more than a few seconds.

---

Process Pools for Heavier Parallelism
-------------------------------------

When you need to run shell commands, external scripts, or long-running subprocesses in parallel, reach for `Process::pool()`.

```php
use Illuminate\Support\Facades\Process;

$results = Process::pool(function ($pool) {
    $pool->command('php artisan import:chunk --start=0 --end=5000');
    $pool->command('php artisan import:chunk --start=5000 --end=10000');
    $pool->command('php artisan import:chunk --start=10000 --end=15000');
})->start()->wait();

foreach ($results as $result) {
    if ($result->failed()) {
        logger()->error($result->errorOutput());
    }
}

```

Each pool entry is a fully independent OS process. You get stdout, stderr, and exit codes per process. This is ideal for data pipeline stages, asset compilation steps, or any work that maps cleanly onto CLI commands.

### Concurrency vs Process Pool — Decision Matrix

| Concern | `Concurrency::run()` | `Process::pool()` | |---|---|---| | PHP closures | ✅ | ❌ | | Shell commands | ❌ | ✅ | | Shared Eloquent models | ❌ (isolated) | ❌ (isolated) | | Return values | ✅ native PHP | stdout only | | Timeout control | Via driver config | Per-process |

---

Avoiding Shared-State Bugs
--------------------------

Both primitives fork or spawn new processes, so **database connections, Redis connections, and in-memory singletons are not shared**. Each child re-bootstraps the application. This means:

- Open transactions in the parent are invisible to children.
- Singleton state (e.g., a tenant resolver) must be re-hydrated inside the closure.
- File handles opened before the fork are duplicated — close them before forking.

```php
// ❌ Wrong: connection opened before fork may corrupt state
$conn = DB::connection();
Concurrency::run([
    fn () => $conn->table('orders')->count(), // unsafe
]);

// ✅ Correct: let each child open its own connection
Concurrency::run([
    fn () => DB::table('orders')->count(),
]);

```

---

Practical Pattern: Parallel Dashboard Aggregates
------------------------------------------------

A common use case is a dashboard endpoint that needs five independent aggregate queries. Without concurrency, these run sequentially. With `Concurrency::run()`, they fan out and the total latency is roughly the slowest single query.

```php
[$revenue, $signups, $churn, $mrr, $tickets] = Concurrency::run([
    fn () => RevenueMetric::thisMonth(),
    fn () => SignupMetric::thisMonth(),
    fn () => ChurnMetric::thisMonth(),
    fn () => MrrMetric::current(),
    fn () => SupportTicket::open()->count(),
]);

```

This pattern is clean, readable, and requires zero queue infrastructure.

---

Key Takeaways
-------------

- Use `Concurrency::run()` for fan-out PHP closures that block until all results are ready.
- Use `Process::pool()` for parallel shell commands where you need stdout/stderr.
- Neither is a queue replacement — both block the calling process.
- Always let children open their own DB/Redis connections; never share handles across a fork.
- Prefer the `process` driver in environments where `pcntl_fork` is unavailable or unsafe.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Flaravel-concurrency-facade-and-process-pools-for-parallel-work-2&text=Laravel+Concurrency+Facade+and+Process+Pools+for+Parallel+Work) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Flaravel-concurrency-facade-and-process-pools-for-parallel-work-2) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Does the Concurrency facade work with Laravel Octane?        The `fork` driver is unsafe inside Octane workers (Swoole/RoadRunner) because forking a long-lived worker process can corrupt shared state. Use the `process` driver instead, which spawns a fresh subprocess and is safe in any environment. 

      Q02  How do I handle exceptions thrown inside a Concurrency closure?        If a child closure throws, `Concurrency::run()` re-throws the exception in the parent. Wrap individual closures in try/catch and return a Result object if you need per-task fault tolerance rather than an all-or-nothing failure. 

      Q03  When should I use Process::pool() instead of dispatching multiple queued jobs?        Process pools are best for synchronous, bounded work where you need results immediately and the total runtime is short (seconds, not minutes). Queued jobs are better for fire-and-forget work, retries, prioritisation, and tasks that may take arbitrarily long. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://www.msaied.com/articles) 

 [ ![Filament v5 Preview: Schema Unification, Performance Shifts, and How to Prepare](https://cdn.msaied.com/340/1a05ca68637b898b676efb66f22e627f.png) filament laravel php 

### Filament v5 Preview: Schema Unification, Performance Shifts, and How to Prepare

Filament v5 is reshaping how panels, forms, and tables are composed. This deep-dive covers the confirmed archi...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 1 Jul 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/filament-v5-preview-schema-unification-performance-shifts-and-how-to-prepare) [ ![Laravel 13: New Features, Helpers, and Practical Upgrade Notes](https://cdn.msaied.com/339/58c4fa6fe9b6d25a2dac17c621b6f4c6.png) laravel laravel-13 upgrade 

### Laravel 13: New Features, Helpers, and Practical Upgrade Notes

Laravel 13 ships with async-first defaults, a leaner bootstrapping layer, and several quality-of-life helpers....

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 1 Jul 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-13-new-features-helpers-and-practical-upgrade-notes) [ ![Laravel 12: Structured Route Files, Slim Skeletons, and the New Application Bootstrapping](https://cdn.msaied.com/337/05b39d16d0f88a5fb94d0cf74049b88b.png) laravel laravel-12 upgrade 

### Laravel 12: Structured Route Files, Slim Skeletons, and the New Application Bootstrapping

Laravel 12 ships with a leaner skeleton, first-class route file organisation, and a revised application bootst...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 1 Jul 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-12-structured-route-files-slim-skeletons-and-the-new-application-bootstrapping) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
