Skip to main content
← All articles
php

Async PHP grew up in 2026 — does a Drupal developer need to care?

Async PHP grew up in 2026 — does a Drupal developer need to care?

Async PHP had a good 2026. Fibers are mature, the ecosystem consolidated onto a shared event loop, and the "PHP can't do concurrency" jokes are finally wrong. So as a Drupal developer, how much of this do you actually need to learn? Honest answer: almost none of it directly — but the small exception is worth knowing, and the reasons why are more interesting than the hype.

What actually landed

The pieces are real and stable now:

  • Fibers (PHP 8.1) are the primitive: a function you can pause and resume. The critical caveat everyone skips — Fibers are not concurrency. Only one runs at a time, and it only yields when it chooses to. They remove the callback/promise "colored function" mess; they do not, by themselves, make two things happen at once.
  • Revolt is the event loop that AMPHP and ReactPHP now share as a common base — so, via adapters, clients from both ecosystems can run on one loop. (Careful phrasing: ReactPHP hasn't replaced its native loop with Revolt; they interoperate through an adapter. "One loop to rule them" is true only once you bridge them.)
  • AMPHP v3 (built on Revolt) lets you write async code that looks synchronous thanks to Fibers, and ReactPHP continues on its long-lived 1.x line. Both give you non-blocking HTTP, streams, and timers.

Concurrency only appears when you combine a Fiber with that event loop driving non-blocking I/O. The loop runs one fiber, it hits a network wait, it yields, the loop runs another. That's cooperative concurrency — genuinely useful, and genuinely not what a normal Drupal page does.

Why Drupal gains almost nothing

Drupal's request lifecycle is synchronous top to bottom, and the anchor holding it there is the database layer: core's DB calls block the whole process. A page request boots the kernel, runs blocking queries, renders, returns, and the process is torn down. There's no event loop, and there's nothing for one to interleave — the request is a straight line of "wait for the DB, wait for the DB, render." Bolting Fibers onto that buys you nothing, because the thing you'd want to overlap (the DB) blocks anyway. There's a long-standing core meta-issue about making Drupal work under persistent app servers precisely because the synchronous DB is the wall.

Fibers let you wait on many things at once. A Drupal page mostly waits on one thing — the database — and it waits on it synchronously. You can't interleave a queue of one.

The one place it matters

There is a real exception, and it's mine as much as anyone's: parallel outbound I/O in a queue worker, batch, or cron job. When I send the weekly newsletter, or if I were fanning out a dozen independent API calls to enrich content, doing them one after another is pure wasted wall-clock — each one is mostly waiting on someone else's server. That's the textbook case for concurrency.

But here's the honest kicker: you almost certainly don't need Fibers or Revolt to do it. Guzzle — which ships with Drupal core — already does async and pooled requests via promises and requestAsync(). You fire N requests, they run concurrently on Guzzle's own loop, you wait for all of them. For the 95% case (parallel HTTP in a worker) that's the tool, and it's already in your vendor directory. Reach for the full async stack only for genuinely long-running CLI daemons — a custom worker process that stays alive and juggles many connections — which is the one shape where a persistent event loop earns its keep.

Doesn't worker mode change this?

A little. FrankenPHP's worker mode (and Swoole, RoadRunner) keep the PHP process alive across requests, which is where a reusable event loop could theoretically live. But Drupal assumes fresh state per request, worker mode already surfaces session and state-leak sharp edges, and the DB is still synchronous — so worker mode mostly buys faster boot and throughput, not app-level async. Even there, Fibers stay in the runtime and the libraries, not in your module code.

So: enjoy that async PHP grew up. Appreciate that Guzzle quietly gives you the one win you'll actually use. And don't feel behind for not writing a single Fiber — for a Drupal dev, that's the correct amount.

Links

BM
Blue Moose
The moose behind Blue Moose. Full-stack PHP developer — Drupal by day, Symfony by night, tests always.