
PHP 8.1 introduced Fibers — a new primitive for managing code execution flow without blocking the entire process.
Think of fibers as lightweight, cooperative threads that allow you to pause and resume code at will. They don’t run in parallel like actual OS threads, but they do give you far more control over execution order compared to callbacks or generators.
Fibers give you:
-
Synchronous-looking async code — readable and easy to maintain.
-
Non-blocking operations without nested callbacks.
-
Full control over execution — you decide when to pause and resume.
How Fibers Work
A Fiber encapsulates a block of code and can:
-
Start execution with
Fiber::start()
-
Suspend itself with
Fiber::suspend()
-
Resume with
Fiber::resume()
-
Throw exceptions back into the fiber with
Fiber::throw()
Basic Example
$fiber = new Fiber(function (): void { echo "Step 1\n"; Fiber::suspend("Paused after Step 1"); echo "Step 2\n"; }); $result = $fiber->start(); echo $result . "\n"; // "Paused after Step 1" $fiber->resume();
Output:
Step 1 Paused after Step 1 Step 2
Real-World Use Cases
1. Non-Blocking HTTP Requests
Imagine you’re fetching data from multiple APIs. Without fibers, each request blocks the next. With fibers, you can write non-blocking code that still looks synchronous.
$urls = ['https://jsonplaceholder.typicode.com/posts/1', 'https://jsonplaceholder.typicode.com/posts/2', 'https://jsonplaceholder.typicode.com/posts/3']; function fetchData(string $url): mixed { // Simulate async request Fiber::suspend("Fetching $url"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); $result = curl_exec($ch); curl_close($ch); return json_decode($result); } $fibers = []; foreach($urls as $url) { $fibers[] = new Fiber(fn() => fetchData($url)); } foreach ($fibers as $fiber) { echo $fiber->start() . "\n"; // Suspends each fiber } // Later, resume all fibers when data is ready foreach ($fibers as $fiber) { $fiber->resume() . "\n"; var_dump($fiber->getReturn()); }
2. Better Async Database Queries
With the right event loop (like in Amphp), you can run multiple queries in parallel without callbacks:
$fiber = new Fiber(function () use ($db) { $users = Fiber::suspend($db->queryAsync('SELECT * FROM users')); $orders = Fiber::suspend($db->queryAsync('SELECT * FROM orders')); return [$users, $orders]; });
When to Use Fibers
-
I/O heavy workloads (network calls, file reads, database queries).
-
Schedulers and cooperative multitasking.
-
Cleaner async code in frameworks like ReactPHP, Amphp, Swoole.
In Conclusion
Fibers don’t replace true multithreading — they just make async code look like sync code. The real win is readability and maintainability. For PHP developers building microservices, APIs, or real-time apps, fibers make complex concurrency patterns far easier to reason about.