Skip to main content

PHP Fibers: asynchronous code without extensions

PHP · 18.10.2026 · 4 min read
Illustration for “PHP Fibers: asynchronous code without extensions”

A Fiber (PHP 8.1+) is a language-level mechanism for pausing and resuming function execution without an extension like Swoole. On its own a Fiber gives neither parallelism nor non-blocking I/O — it only manages the return point, while non-blocking network and file operations on top come from scheduler libraries such as Revolt or amphp.

What a Fiber does, and does not do

A Fiber wraps a function in an object that can be started, paused from inside and resumed from outside, passing values both ways. It is a low-level primitive — a context switch with no new OS process or thread, inside one PHP process.

A Fiber does not make a network call non-blocking by itself: without an event loop around it, suspend simply stops execution until an explicit resume. That event loop (Revolt, amphp) is what turns a set of Fibers into real asynchronous code running several tasks at once.

A minimal example: start, suspend, resume

Below is literally the whole mechanics of a Fiber with no scheduler library: the function pauses inside itself, and the code outside decides when to resume it and what to pass back.

$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('started');
    echo $value, PHP_EOL;
});
$fiber->start();
$fiber->resume('resumed');

How this differs from Swoole coroutines

Swoole provides a ready event loop, non-blocking I/O at the extension level and its own HTTP server — all covered in the article on Swoole and RoadRunner. A Fiber is only the language's basic building block, on top of which libraries like Revolt build the same kind of event loop without a C extension, trading some speed for portability to any hosting with PHP 8.1 or newer.

  • a scheduler wrapper (Revolt, amphp) is required — without one a Fiber gives no concurrency
  • there is no built-in non-blocking client for MySQL or Redis, unlike Swoole
  • it works in any CLI and FPM environment with no extension to install
  • switching between Fibers is cheaper than creating a thread but pricier than a plain function call
  • exceptions inside a Fiber must be caught explicitly on resume, otherwise they are lost

Where a Fiber is actually useful in practice

A Fiber fits where a script performs several independent waits — several HTTP requests to external APIs, several queue lookups — and runs in an ordinary PHP CLI process rather than under Swoole. The difference between running such long scripts via CLI and via FPM is covered in the article on PHP in cron.

A Fiber does not replace a message queue: it speeds up waiting inside a single process, but gives no isolation from a process crash and does not restart a task by itself. Reliable queue worker restarts through Supervisor remain a separate topic, covered in the article on PHP queues and Supervisor.

Table: approaches to concurrency in PHP

The table compares mechanisms, not speed — the actual performance difference depends on the task and must be measured separately.

ApproachExtension neededTypical task
Plain blocking PHPnoa simple script, one task at a time
Fiber + Revolt or amphpnoseveral independent HTTP requests in a CLI script
Swooleyesa long-lived server with coroutines and its own HTTP server
RoadRunnerno, a separate binarylong-lived PHP workers behind a Go server

Frequently asked questions

Should code be rewritten with Fibers just to speed up an ordinary site?

No: if the site is served through PHP-FPM with one request per process, a Fiber speeds up nothing without an event loop around it and without moving to long-lived workers.

Can Fibers be used together with Swoole?

Yes, Swoole itself is built on a similar context-switching idea and provides its own coroutines, which in many versions are compatible with Revolt-based code inside the same process.

What happens to an exception inside a Fiber if it is not caught?

The exception surfaces on the next call to resume on that Fiber, not at the moment it is thrown inside the function — if the calling code does not wrap resume in try-catch, the exception interrupts execution just like a regular uncaught exception.

Was this article helpful?
← Back to Knowledge Base Ask Support