Fibers and Async PHP

By the end of this lesson you'll understand PHP 8.1 Fibers — how to start , suspend , resume , and read a Fiber's getReturn value — what cooperative multitasking really means, how async runtimes like ReactPHP, Amp, and Swoole use Fibers to do non-blocking I/O without callbacks, and how generators ( yield ) compare.

Learn Fibers and Async PHP in our free PHP course — an interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ PHP Is Synchronous by Default

Out of the box, PHP runs one statement after another and blocks on I/O — a call like file_get_contents() stops the whole script until it returns. For a single web request that's simple and fast. But if one process must make many slow calls, it spends almost all its time waiting , doing nothing useful.

Notice slowFetch("b") can't even begin until slowFetch("a") has completely finished. Fibers give us a way to overlap that waiting.

2️⃣ Your First Fiber: start & suspend

A Fiber (PHP 8.1) is a block of code you can pause and resume , and it keeps its own call stack while paused. You wrap a callback in new Fiber(...) , then start() it. Inside, Fiber::suspend($value) pauses and hands $value back to the caller; $fiber->resume($value) continues it, and that argument becomes the result of the suspend() call.

Read the numbered lines in order: control ping-pongs between the Fiber and the outside code. The Fiber runs to its suspend() , hands a value out, and waits — exactly one of them is ever running at a time.

3️⃣ Suspending Repeatedly & getReturn

A Fiber can suspend many times, then finish by returning a value. You drive it in a loop with resume() until isTerminated() is true, and read the final value with $fiber->getReturn() .

This pause-report-resume loop is the heart of a scheduler: each pass lets the Fiber make a little progress, then yields control so other work can run before it's resumed.

4️⃣ How Async Runtimes Use Fibers

Cooperative multitasking means each task runs until it voluntarily yields by suspending — nothing interrupts it, so there are no data races. Async runtimes ( ReactPHP , Amp , Swoole ) build an event loop on top of this: when your code awaits a network call, the runtime suspends the Fiber, lets the loop run other Fibers, and resumes yours when the data arrives. The result is async code that reads like ordinary blocking code — no callback pyramids.

Both requests start before either response arrives — that's the overlap. In a real runtime the resume() calls are triggered by I/O completions, not a simple loop, but the shape is identical. This is also what powers long-lived WebSocket servers.

5️⃣ Generators (yield) vs Fibers

You may have met yield before — generators also pause and resume. The key difference: a generator can only yield from its own top-level body and is shaped like an iterator. A Fiber can suspend() from deep inside any nested function it calls, several frames down — which is precisely what makes transparent async possible, since the suspend point usually lives inside a library's networking code, not in your function.

Generators were PHP's older, more limited tool for this. Fibers, added in 8.1, removed the restriction — which is why modern async frameworks moved onto them.

Now you try the two core skills — the start/suspend handshake, and reading a return value.

Fill in each ___ using the 👉 hint, then run it and check it against the Output panel.

One more. Let the Fiber finish, then read the value it returned.

📋 Quick Reference — Fibers

No code is filled in this time — just a brief and an outline. Build three Fibers, start them all, then resume them all, and watch the interleaving. This is the essence of how an event loop overlaps work without threads.

Practice quiz

In which PHP version were Fibers introduced?

  • PHP 8.1
  • PHP 7.4
  • PHP 8.0
  • PHP 5.6

Answer: PHP 8.1. Fibers landed in PHP 8.1, giving the language a low-level primitive for pausing and resuming a block of code.

What is a Fiber, in one sentence?

  • A new kind of array
  • A full-featured OS thread that runs truly in parallel
  • A block of code you can pause and later resume, keeping its own call stack
  • A database connection pool

Answer: A block of code you can pause and later resume, keeping its own call stack. A Fiber is a unit of execution with its own stack that can suspend itself and be resumed later from the same point. It is cooperative, not parallel.

By default, how does PHP execute code?

  • Asynchronously with a built-in event loop
  • Synchronously, one statement after another, blocking on I/O
  • Randomly
  • In parallel across all CPU cores

Answer: Synchronously, one statement after another, blocking on I/O. PHP is synchronous and blocking by default: a call like file_get_contents waits until it finishes before the next line runs.

Which method starts a Fiber running?

  • $fiber->begin()
  • $fiber->go()
  • $fiber->run()
  • $fiber->start()

Answer: $fiber->start(). $fiber->start() begins execution; any arguments you pass become the arguments of the Fiber's callback. It runs until the first suspend or until it returns.

What does Fiber::suspend($value) do?

  • Pauses the current Fiber and hands $value back to whoever called start() or resume()
  • Throws an exception
  • Starts a new Fiber
  • Permanently stops the Fiber

Answer: Pauses the current Fiber and hands $value back to whoever called start() or resume(). Fiber::suspend() is called from inside the Fiber. It pauses execution and returns its argument to the outside code that resumed it.

What does $fiber->resume($value) do?

  • Restarts the Fiber from the beginning
  • Continues a suspended Fiber, and $value becomes the return value of the suspend() call inside it
  • Kills the Fiber
  • Returns the Fiber's final value

Answer: Continues a suspended Fiber, and $value becomes the return value of the suspend() call inside it. resume() continues a suspended Fiber from where it paused, and the value you pass becomes the result of the Fiber::suspend() call that paused it.

How do you read the value a Fiber returned after it finishes?

  • $fiber->output()
  • $fiber->result()
  • $fiber->value()
  • $fiber->getReturn()

Answer: $fiber->getReturn(). Once a Fiber's callback has returned (and the Fiber is terminated), $fiber->getReturn() gives you that final return value.

What style of multitasking do Fibers provide?

  • No multitasking at all
  • Preemptive multitasking, where PHP interrupts code at any time
  • Cooperative multitasking, where code yields control voluntarily by suspending
  • True parallelism across cores

Answer: Cooperative multitasking, where code yields control voluntarily by suspending. Fibers are cooperative: a Fiber keeps running until it chooses to suspend. Nothing interrupts it, so there are no data races from preemption.

How do event-loop runtimes like ReactPHP, Amp, and Swoole use Fibers?

  • They replace PHP with Node.js
  • They suspend a Fiber while an I/O operation is pending and resume it when the data is ready, so async code reads like sync code
  • They run each Fiber on a separate CPU core
  • They compile Fibers to machine code

Answer: They suspend a Fiber while an I/O operation is pending and resume it when the data is ready, so async code reads like sync code. Async runtimes drive an event loop. When a Fiber awaits I/O they suspend it, let the loop do other work, and resume it when the result arrives, removing callback nesting.

What is the main difference between a generator (yield) and a Fiber?

  • A generator can only suspend at its own top level and is iterator-shaped; a Fiber can suspend from deep inside any nested function call
  • Generators run in parallel, Fibers do not
  • There is no difference
  • Generators are faster than Fibers in every case

Answer: A generator can only suspend at its own top level and is iterator-shaped; a Fiber can suspend from deep inside any nested function call. yield only pauses the generator function itself. Fiber::suspend() can pause from anywhere in the call stack beneath the Fiber, which is what makes transparent async possible.