Laravel Concurrency Facade &amp; Process Pools | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://msaied.com/public) - [Home](https://msaied.com/public)
- [Projects](https://msaied.com/public/projects)
- [Articles](https://msaied.com/public/articles)
- [Certificates](https://msaied.com/public/certificates)
- [About](https://msaied.com/public#about)

           [  Contact](https://msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://msaied.com/public)
- [ProjectsCase studies](https://msaied.com/public/projects)
- [ArticlesEngineering notes](https://msaied.com/public/articles)
- [CertificatesCredentials](https://msaied.com/public/certificates)
- [AboutHow I work](https://msaied.com/public#about)
- [ContactGet in touch](https://msaied.com/public#contact)

  [Start a conversation](https://msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://msaied.com/public)
2. /
3. [Articles](https://msaied.com/public/articles)
4. /
5. Concurrency in Laravel: Process Pools, Fibers, and the Concurrency Facade

 Concurrency in Laravel: Process Pools, Fibers, and the Concurrency Facade
==========================================================================

 Laravel's Concurrency facade and process pools let you run independent work in parallel without reaching for a queue. Here's how to use them safely and effectively in production PHP applications.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://msaied.com/public#person) Published 26 Jul 2026 · Updated 26 Jul 2026 · 4 min read

ShareCopy linkCopied

 ![Concurrency in Laravel: Process Pools, Fibers, and the Concurrency Facade](https://cdn.msaied.com/471/ba1a628c196e92cbb81033c865c9ad26.png) 

  On this page +1. [Why Concurrency Matters Before You Reach for a Queue](#why-concurrency-matters-before-you-reach-for-a-queue)
2. [The Concurrency Facade](#the-concurrency-facade)
3. [What Gets Serialized](#what-gets-serialized)
4. [Process Pools for Lower-Level Control](#process-pools-for-lower-level-control)
5. [Timeouts and Error Handling](#timeouts-and-error-handling)
6. [PHP Fibers: Cooperative Concurrency Without Forking](#php-fibers-cooperative-concurrency-without-forking)
7. [Production Considerations](#production-considerations)
8. [Key Takeaways](#key-takeaways)

 Why Concurrency Matters Before You Reach for a Queue
----------------------------------------------------

Queues are the right tool for deferred, durable work. But sometimes you need to fan out several independent HTTP calls, database reads, or CPU-bound transforms *right now*, within a single request, and collect the results before responding. Laravel's `Concurrency` facade (introduced in Laravel 11) and the underlying `Process` facade give you two clean primitives for this.

---

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

The `Concurrency` facade runs an array of closures in parallel using forked PHP processes under the hood. Each closure is serialized, executed in a child process, and the results are collected back into the parent.

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

[$prices, $inventory, $reviews] = Concurrency::run([
    fn () => PricingService::fetch(productId: 42),
    fn () => InventoryService::fetch(productId: 42),
    fn () => ReviewService::summary(productId: 42),
]);

```

All three calls happen in parallel. The parent blocks until every child finishes, then returns results in the same order as the input array.

### What Gets Serialized

Because each closure runs in a forked process, anything captured in the closure must be serializable. Eloquent models, DTOs, and scalar values are fine. Database connections, open file handles, and non-serializable objects are **not** — they will cause silent failures or exceptions.

```php
// ✅ Safe — scalar captured
$id = $product->id;
Concurrency::run([fn () => SomeService::fetch($id)]);

// ❌ Unsafe — Eloquent model captured directly
Concurrency::run([fn () => SomeService::fetch($product)]);

```

---

Process Pools for Lower-Level Control
-------------------------------------

When you need more control — custom environment variables, timeouts, or shell commands — the `Process` facade's pool API is the right layer.

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

$results = Process::pool(function ($pool) {
    $pool->command('php artisan report:generate --type=sales');
    $pool->command('php artisan report:generate --type=inventory');
    $pool->command('php artisan report:generate --type=returns');
})->start()->wait();

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

```

Each `command` runs as a real OS process. `start()` launches them all immediately; `wait()` blocks until every process exits and returns a `ProcessPoolResults` collection.

### Timeouts and Error Handling

```php
Process::pool(function ($pool) {
    $pool->timeout(30)->command('php artisan export:csv --month=2025-05');
    $pool->timeout(10)->command('php artisan notify:slack');
})->start()->wait();

```

A timed-out process throws `ProcessTimedOutException` on `wait()`. Wrap the call in a try/catch and decide whether to retry or degrade gracefully.

---

PHP Fibers: Cooperative Concurrency Without Forking
---------------------------------------------------

Fibers (PHP 8.1+) are cooperative, not preemptive — they do not give you true parallelism. They are useful for interleaving I/O-bound work within a single thread, which is exactly how async libraries like ReactPHP and Revolt use them. Laravel itself uses Fibers internally in some Octane contexts.

For most Laravel applications, reach for `Concurrency::run()` or `Process::pool()` before writing raw Fiber code. Fibers shine when you control the event loop; in a standard FPM request, forked processes are simpler and safer.

---

Production Considerations
-------------------------

- **Worker limits**: Each forked process inherits the parent's memory footprint. On a 512 MB container, running 10 concurrent forks can exhaust memory quickly. Benchmark your payload size.
- **Database connections**: Child processes do not inherit open PDO connections safely. Let each child open its own connection via the service container.
- **Octane compatibility**: Under Octane, forked processes can inherit shared state. Prefer `Process::pool()` with artisan commands when running under Octane to avoid state leakage.
- **Observability**: Exceptions in child processes surface as serialized `Throwable` instances. Log them explicitly — they will not bubble up to your default exception handler automatically.

---

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

- Use `Concurrency::run()` for parallel PHP closures when results are needed immediately in the same request.
- Capture only serializable values in closures — never raw Eloquent models or connections.
- Use `Process::pool()` when you need OS-level process control, timeouts, or shell commands.
- PHP Fibers are cooperative, not parallel — they are not a replacement for process-based concurrency in FPM.
- Always account for memory multiplication and connection limits when sizing concurrent workloads.

- [laravel](https://msaied.com/public/articles?search=laravel)
- [concurrency](https://msaied.com/public/articles?search=concurrency)
- [php](https://msaied.com/public/articles?search=php)
- [performance](https://msaied.com/public/articles?search=performance)
- [process-pools](https://msaied.com/public/articles?search=process-pools)

 Frequently asked questions 
---------------------------

  Does Concurrency::run() work under Laravel Octane?It can, but forked processes inherit the parent worker's state, which can cause subtle bugs with shared singletons or open connections. Under Octane, prefer Process::pool() with artisan commands to get clean process isolation.

   What happens if one closure in Concurrency::run() throws an exception?The exception is serialized and re-thrown in the parent process when results are collected. Other closures that already completed are not rolled back, so design each unit of work to be independently safe to fail.

   Is there a limit to how many closures I can pass to Concurrency::run()?There is no hard framework limit, but each closure spawns a forked process. Practical limits come from OS process limits, available memory, and file descriptor counts. Keep pools small (2–8 tasks) and benchmark under realistic load.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

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

[About](https://msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleLaravel Queues in Production: Horizon Tuning, Metrics, and Graceful Scaling](https://msaied.com/public/articles/laravel-queues-in-production-horizon-tuning-metrics-and-graceful-scaling) [Next articleFilament v4 Migrating from v3: Breaking Changes and Refactor Patterns](https://msaied.com/public/articles/filament-v4-migrating-from-v3-breaking-changes-and-refactor-patterns)  

   On this page
-------------

1. [Why Concurrency Matters Before You Reach for a Queue](#why-concurrency-matters-before-you-reach-for-a-queue)
2. [The Concurrency Facade](#the-concurrency-facade)
3. [What Gets Serialized](#what-gets-serialized)
4. [Process Pools for Lower-Level Control](#process-pools-for-lower-level-control)
5. [Timeouts and Error Handling](#timeouts-and-error-handling)
6. [PHP Fibers: Cooperative Concurrency Without Forking](#php-fibers-cooperative-concurrency-without-forking)
7. [Production Considerations](#production-considerations)
8. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/745/8744e1be5136b430da52e9fca3ed3964.png)  · 3 min read### Service Container Deep Dive: Contextual Binding, Tagging, and Method Injection

6 Oct 2026 ](https://msaied.com/public/articles/service-container-deep-dive-contextual-binding-tagging-and-method-injection-1) [ ![](https://cdn.msaied.com/743/8998fac3a41451ab3fe1588194e17a43.png) Filament · 3 min read### Securing Filament Plugins with Plumb: Automated Security Scoring for PHP Packages

5 Oct 2026 ](https://msaied.com/public/articles/securing-filament-plugins-with-plumb-automated-security-scoring-for-php-packages) [ ![](https://cdn.msaied.com/742/2d02018669cdeedccb5de2efb898f0ee.png) Filament · 3 min read### Filament v3.3.56 Released: File Hash Names and Livewire Upload Fix

5 Oct 2026 ](https://msaied.com/public/articles/filament-v3356-released-file-hash-names-and-livewire-upload-fix) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://msaied.com/public)
- [Articles](https://msaied.com/public/articles)
- [Certificates](https://msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://msaied.com/public/sitemap.xml)
