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.
| Approach | Extension needed | Typical task |
|---|---|---|
| Plain blocking PHP | no | a simple script, one task at a time |
| Fiber + Revolt or amphp | no | several independent HTTP requests in a CLI script |
| Swoole | yes | a long-lived server with coroutines and its own HTTP server |
| RoadRunner | no, a separate binary | long-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.