PHP Fibers

Ma Mariya Vinciya Updated 21 Oct 2026
5 min read ·Lesson 168 of 174
In this post

What Is a Fiber? In simple terms: A fiber is a function that can pause itself in the middle of its work and be resumed later , exactly where it stopped, with all its variables intact. While it is paus

What Is a Fiber?

In simple terms: A fiber is a function that can pause itself in the middle of its work and be resumed later, exactly where it stopped, with all its variables intact. While it is paused, the rest of the program continues. This makes it possible to interleave several tasks — run a bit of task A, then a bit of task B, then continue A — within a single PHP process.

Technically: Fibers (PHP 8.1+) are interruptible functions with their own call stack. A Fiber object wraps a callable. start() begins executing it; inside, Fiber::suspend() pauses the fiber — even from deep inside nested function calls — and returns control to the code that started or resumed it. resume() continues the fiber. Values can be passed in both directions. Fibers provide cooperative concurrency: only one fiber runs at a time, and each one decides when to pause.

Fibers vs Generators

GeneratorFiber
Pausingyield, only directly inside the generator functionFiber::suspend(), from any depth of nested calls
Caller awarenessCallers must know they are dealing with a generatorCode inside the fiber looks like normal synchronous code
Main useLazy sequences of valuesBuilding asynchronous frameworks and schedulers

 


The Fiber Lifecycle

<?php
$fiber = new Fiber(function (string $greeting): string {
    echo "Fiber started with: $greeting\n";

    $received = Fiber::suspend('paused once');

    echo "Fiber resumed with: $received\n";

    return 'done';
});

$value = $fiber->start('hello');
echo "Main received: $value\n";

$fiber->resume('continue');

echo "Fiber returned: " . $fiber->getReturn() . "\n";
var_dump($fiber->isTerminated());

 

Output

Fiber started with: hello
Main received: paused once
Fiber resumed with: continue
Fiber returned: done
bool(true)

 

How It Works

Main code                          Fiber
─────────                          ─────
$fiber->start('hello')  ───────►   runs: "Fiber started with: hello"
                        ◄───────   Fiber::suspend('paused once')
"Main received: paused once"
$fiber->resume('continue') ────►   suspend() returns 'continue'
                                   runs: "Fiber resumed with: continue"
                        ◄───────   return 'done'  (fiber terminated)
$fiber->getReturn() → 'done'

 

  1. start('hello') runs the fiber's function with 'hello' as its argument until the first Fiber::suspend().
  2. Fiber::suspend('paused once') pauses the fiber and hands 'paused once' back as the return value of start().
  3. resume('continue') continues the fiber; inside, Fiber::suspend() now returns 'continue'.
  4. When the function returns, the fiber is terminated, and getReturn() provides its return value.

The Fiber API

MethodPurpose
new Fiber(callable $callback)Create a fiber (it does not run yet)
$fiber->start(...$args)Start it; returns the value passed to the first suspend() (or null if it finishes)
Fiber::suspend($value)Pause the current fiber, sending $value out; returns the value passed to resume()
$fiber->resume($value)Continue a suspended fiber
$fiber->throw($exception)Resume the fiber by throwing an exception inside it
$fiber->getReturn()The return value after termination
isStarted(), isSuspended(), isRunning(), isTerminated()Status checks
Fiber::getCurrent()The currently running fiber, or null

 


Suspending From Deep Inside Nested Calls

The key ability of fibers: code several function calls deep can pause the whole fiber, without the intermediate functions knowing about it:

<?php
function fetchFromApi(string $resource): string
{
    // Pretend to wait for a network response
    $response = Fiber::suspend("waiting for $resource");
    return $response;
}

function buildDashboard(): string
{
    $orders = fetchFromApi('/orders');
    $stock = fetchFromApi('/stock');

    return "Dashboard: $orders, $stock";
}

$fiber = new Fiber(buildDashboard(...));

echo $fiber->start() . "\n";
echo $fiber->resume('12 orders') . "\n";
$fiber->resume('3 items low');

echo $fiber->getReturn() . "\n";

 

Output

waiting for /orders
waiting for /stock
Dashboard: 12 orders, 3 items low

 

buildDashboard() reads like ordinary sequential code. The pausing happens inside fetchFromApi(), and the main code (acting as a simple "event loop") decides when to deliver each response. This is how asynchronous libraries hide their complexity: the application code stays simple.


A Tiny Scheduler: Interleaving Tasks

<?php
function task(string $name, int $steps): Closure
{
    return function () use ($name, $steps): void {
        for ($step = 1; $step <= $steps; $step++) {
            echo "$name: step $step\n";
            Fiber::suspend();   // give other tasks a turn
        }
    };
}

$fibers = [
    new Fiber(task('Import', 3)),
    new Fiber(task('Email', 2)),
];

foreach ($fibers as $fiber) {
    $fiber->start();
}

while ($fibers !== []) {
    foreach ($fibers as $index => $fiber) {
        if ($fiber->isTerminated()) {
            unset($fibers[$index]);
            continue;
        }
        $fiber->resume();
    }
}

echo "All tasks finished\n";

 

Output

Import: step 1
Email: step 1
Import: step 2
Email: step 2
Import: step 3
All tasks finished

 

Step-by-Step Explanation

  1. Each task runs one step and then suspends, yielding control to the scheduler.
  2. The scheduler starts all fibers, then resumes each suspended fiber in turn (round-robin).
  3. When a fiber's function finishes, it becomes terminated and is removed from the list.
  4. The steps of both tasks are interleaved, although only one runs at any moment.

What Fibers Do Not Do

Fibers are not threads, and they do not make blocking code non-blocking:

  • Only one fiber runs at a time; there is no parallel execution on multiple CPU cores.
  • A blocking call (sleep(), file_get_contents() on a slow URL, a PDO query) inside a fiber still blocks the entire process.
  • Real concurrency requires an event loop with non-blocking I/O, which pauses a fiber while it waits for a network response and resumes it when data arrives.

In practice, application developers rarely use fibers directly. Libraries build on them:

LibraryPurpose
RevoltA shared event loop for PHP
AMPHP (v3+)Asynchronous HTTP clients, servers, databases, and more, using fibers
ReactPHPEvent-driven, non-blocking I/O (with fiber-based await() helpers)

 

With these, code such as $response = $client->request($request); looks synchronous but lets other requests proceed while waiting.


Common Mistakes

Resuming a Fiber That Is Not Suspended

Effect: FiberError: Cannot resume a fiber that is not suspended (for example, after it has terminated).

Fix: Check isSuspended() before resuming.

Calling Fiber::suspend() Outside a Fiber

Effect: FiberError: Cannot suspend outside of fiber.

Fix: Only suspend from code running inside a fiber.

Expecting Parallelism

Effect: CPU-heavy tasks run no faster, and blocking I/O still blocks.

Fix: Use an async library with non-blocking I/O, or separate processes/queues for parallel work.

Reading getReturn() Too Early

Effect: FiberError when the fiber has not terminated.

Fix: Check isTerminated() first.


Best Practices

  • Understand fibers as the foundation of async libraries rather than as an everyday tool.
  • Use established libraries (Revolt, AMPHP, ReactPHP) for concurrent I/O.
  • Keep fiber-based code free of blocking calls.
  • Check fiber state before resuming or reading return values.
  • Use queues and worker processes for CPU-heavy or long-running background work.

Official reference: https\://www.php.net/manual/en/language.fibers.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where Debugging PHP Project: Image Upload Gallery $_SESSION $_ENV PHP RegEx RegEx Patterns Heredoc and Nowdoc RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures Composer
Ask about this post
AI Ask about this post

Ask questions about PHP Fibers and get answers drawn from it.

Signed-in readers only.