f in x
PHP 8.1 Fibers: Asynchronous Programming Without Complex Event Loops
> cd .. / HUB_EDITORIALE
Sviluppo di siti web

PHP 8.1 Fibers: Asynchronous Programming Without Complex Event Loops

[2026-05-29] Author: Ing. Calogero Bono

Concurrency in PHP has always been a rough terrain. For decades, every HTTP request meant a single process, and slow I/O operations (API calls, database queries, file reads) blocked the entire script. Traditional solutions — child processes with pcntl_fork, job queues (Beanstalkd, RabbitMQ), or C extensions like event — introduced complexity and overhead. With PHP 8.1, Fibers changed the paradigm. They offer a cooperative concurrency model that allows suspending and resuming arbitrary functions, making asynchronous programming finally accessible to every PHP developer. This guide explores what they are, how to use them, and why they can replace processes and queues in many real-world scenarios.

What Are Fibers in PHP 8.1

A Fiber is a lightweight execution unit that can be suspended from within and resumed from outside. Unlike threads, Fibers do not execute code in parallel: the context remains single, but CPU is voluntarily yielded (yield) to let other Fibers advance. This is called cooperative multitasking.

Suspend and Resume Mechanism

The Fiber class exposes two fundamental methods: suspend() (static) and resume(). Inside a Fiber, you call Fiber::suspend($value) to pause execution and pass a value to the caller. The caller (usually an event loop) receives that value and can decide when to resume the Fiber with $fiber->resume($anotherValue).


$fiber = new Fiber(function (): void {
    $first = Fiber::suspend('Hello');
    $second = Fiber::suspend('World');
    echo $first . ' ' . $second;
});

$result1 = $fiber->start();     // 'Hello'
$result2 = $fiber->resume('Ciao'); // internally returns 'World', but echoes 'Ciao World'

This mechanism allows writing code that looks synchronous but behaves asynchronously, eliminating the need for explicit callbacks or promise chains.

Fibers vs Promises: A Practical Comparison

Promises (like those of ReactPHP, Amp, or Guzzle) have dominated PHP asynchrony for years. They require an explicit event loop and transform the logical flow into chains of then(). Fibers, on the other hand, preserve linear code structure.

Example: Two HTTP Requests in Parallel

Imagine fetching two external URLs. With ReactPHP promises:


use React\Http\Browser;
use React\EventLoop\Loop;

$loop = Loop::get();
$client = new Browser($loop);

$promise1 = $client->get('https://api.example.com/data1');
$promise2 = $client->get('https://api.example.com/data2');

$both = \React\Promise\all([$promise1, $promise2]);
$both->then(function (array $responses) {
    // process
});
$loop->run();

With Fibers, you can use a library that integrates Fibers and an event loop (e.g., Amp v3) to write:


use function Amp\delay;
use function Amp\async;
use function Amp\Http\Client\request;

$response1 = request('https://api.example.com/data1');
$response2 = request('https://api.example.com/data2');

$body1 = $response1->getBody()->buffer();
$body2 = $response2->getBody()->buffer();
// Code looks synchronous but executes requests in parallel

The Fiber-based syntax is closer to traditional PHP, reducing the learning curve.

Practical Implementation: An Async HTTP Client with Fibers

To understand the potential, let's build a small example that executes three HTTP requests in parallel using only Fibers and a simulated non-blocking I/O. Note: in production, use libraries like amphp/http-client or react/http.


// Simulate an async call with sleep (non-blocking? No, but for illustration)
function fetchUrl(string $url, float $delay): string {
    // In real code, use non-blocking sockets and select()
    usleep((int)($delay * 1_000_000));
    return "Response from $url\n";
}

$fiber1 = new Fiber(function () {
    return fetchUrl('https://api1.example.com', 0.2);
});
$fiber2 = new Fiber(function () {
    return fetchUrl('https://api2.example.com', 0.3);
});
$fiber3 = new Fiber(function () {
    return fetchUrl('https://api3.example.com', 0.1);
});

$fiber1->start();
$fiber2->start();
$fiber3->start();

// Simulate a rudimentary event loop
$running = true;
while ($running) {
    $running = false;
    foreach ([$fiber1, $fiber2, $fiber3] as $fiber) {
        if (!$fiber->isTerminated()) {
            $fiber->resume();
            $running = true;
        }
    }
}

echo $fiber1->getReturn();
echo $fiber2->getReturn();
echo $fiber3->getReturn();

In reality, a proper event loop handles scheduling and network resources. But the principle is clear: Fibers let you write parallel code linearly.

Fibers as an Alternative to Processes and Queues

Often, to execute concurrent operations in PHP, developers resort to pcntl_fork (for true CPU parallelism on multi-core) or queue systems (Redis, RabbitMQ). Fibers do not provide CPU parallelism (single-thread), but they excel for I/O-bound operations: HTTP calls, file reads, slow database queries.

Advantages over Separate Processes

  • No process creation overhead: Fibers share the parent process memory.
  • Immediate communication: shared variables without pipes or serialized messages.
  • Simpler error handling: exceptions propagate naturally.

Advantages over Queues

  • Reduced latency: no pass through an external broker.
  • Direct synchronization: a Fiber's result can be awaited in the same script.
  • More compact code: no need to configure workers, queues, and failure handling.

This does not mean processes and queues are obsolete. For CPU-intensive workloads (image processing, long calculations) or tasks that must survive a server restart, processes and queues remain the best choice. Fibers are an additional tool for I/O concurrency.

Best Practices and Common Pitfalls

Using Fibers requires attention:

  • Never block a Fiber with sleep() or synchronous I/O: the fiber blocks and stalls the entire event loop. Replace with async versions (e.g., usleep is not async, avoid).
  • Handle exceptions: an unhandled Fiber exception propagates to the caller of resume(). Use try/catch around resume().
  • Concurrency limit: avoid creating thousands of Fibers simultaneously. Each Fiber occupies a stack (default 8KB). For many simultaneous connections, use a pool or libraries like amphp that manage active Fiber count.
  • Don't overuse Fibers: if the work is CPU-bound, Fibers provide no benefit. Use processes or threads (with pthreads or appropriate extensions).

Conclusion and Next Steps

PHP 8.1 Fibers represent a qualitative leap for asynchronous programming in PHP. They allow writing readable concurrent code without the cognitive load of promises or the complexity of processes. We have seen how to suspend and resume execution, compared Fibers with traditional promises, and analyzed scenarios where they replace queues and processes. For deeper information, consult the official PHP documentation on Fibers and check out the Amp v3 framework, which natively integrates Fibers. If you want to explore other aspects of modern PHP, read the guide Modern PHP 8 or compare with the use of Readonly Properties and Enums.

Final best practice: start by replacing a simple script that performs multiple synchronous HTTP requests with a Fiber-based approach. Measure response times and observe the immediate improvement. Then gradually introduce Fibers into import/export workflows and APIs that must aggregate data from multiple sources.

Sponsored Protocol

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Co-founder di Meteora Web. Ingegnere informatico, sviluppo ecosistemi digitali ad alte prestazioni. AI, automazione, SEO tecnica e infrastrutture web. Scrivo di tecnologia per rendere complesso… semplice.

[ Read Full Dossier ]

Hai bisogno di applicare questa strategia?

Esegui il protocollo di contatto per iniziare un progetto con noi.

> INIZIA_PROGETTO

Sponsored

> MW_JOURNAL

> READ_ALL()