Fibers — Cooperative Concurrency (PHP 8.1)
debt(d9/e5/b5/t7)
Closest to 'silent in production until users hit it' (d9). The detection_hints field explicitly states automated=no and the code_pattern is simply `new Fiber|Fiber::suspend`. No linter or SAST tool is listed that catches the misconception (using Fibers expecting parallelism or without an event loop). The code runs silently — fibers just take turns single-threaded — and the failure mode is subtle performance or correctness issues that only surface under load or async workloads, not compile-time or lint errors.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix states 'Use Fibers via Revolt/ReactPHP event loop rather than directly.' Switching from raw Fiber usage to an event-loop-based abstraction (Revolt/ReactPHP) requires restructuring concurrency code across the async layer of an application — not a one-liner, but not necessarily a full cross-codebase rewrite either. It's a significant refactor within the async/concurrency component.
Closest to 'persistent productivity tax' (b5). Fibers apply only to cli and queue-worker contexts (not general web), which limits reach. However, if an application adopts raw Fibers directly rather than through an event loop abstraction, every future maintainer working on async/concurrency code must understand the fiber scheduling model, and the lack of an event loop creates a persistent structural gap. This imposes an ongoing productivity tax on async workstreams without defining the entire system shape.
Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The misconception is explicit: developers expect Fibers to provide parallelism (as goroutines, threads, or Node.js worker_threads do), but they are cooperative concurrency on a single thread. This directly contradicts how similar async primitives work in Go, Java virtual threads, and Node.js. Additionally, Fibers are confused with PHP generators (both suspend execution, but fibers can suspend from any call depth). Two documented serious traps push this to t7.
TL;DR
Explanation
Fiber::create($callback) creates a fiber. $fiber->start($args) begins execution. Fiber::suspend($value) pauses and returns value to caller. $fiber->resume($value) continues from the suspension point. Fibers are single-threaded — not parallel. They enable: event-loop integration (ReactPHP, Revolt, Swoole), cooperative multitasking, coroutine-style async code without callbacks. The Revolt event loop uses Fibers to implement async/await-like patterns. Unlike generators, Fibers can suspend from any call depth (generators only yield from the generator function itself). This is the PHP equivalent of Python's asyncio coroutines.
Common Misconception
Why It Matters
Common Mistakes
- Expecting Fibers to use multiple CPU cores — they're single-threaded.
- Using Fibers without an event loop — fibers alone don't help without something to schedule them.
- Confusing with PHP generators — fibers can suspend from any call depth.
Code Examples
// Generators only yield from generator function:
function gen() {
yield doSomething(); // Only works at generator level
}
$fiber = new Fiber(function(): void {
$value = Fiber::suspend('first');
echo 'Resumed with: ' . $value . PHP_EOL;
});
$yielded = $fiber->start(); // 'first'
$fiber->resume('hello'); // 'Resumed with: hello'
// Real use: Revolt event loop
// use Revolt\EventLoop;
// EventLoop::run();