ReactPHP's meta repository ships no loop, only the map to it
Event-driven, non-blocking I/O with PHP.
At a glance
- What is it?
- reactphp/reactphp is the index of the ReactPHP component family, not the event loop itself. Its README and its own top-level file list disagree about what you get if you clone it.
- Who is it for?
- Adopt ReactPHP when one process has to hold many idle-open TCP or HTTP connections and your team can write against Promises/A instead of blocking calls. Do not adopt it to speed up CPU-bound PHP, and do not treat this repository as the library itself, since cloning it yields a README, a composer.json and two phpunit configs with no src directory in sight.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The repository you clone holds an index, not a loop
reactphp/reactphp is not the event loop. Its own README calls the repository a meta repository used to discuss and plan everything @ReactPHP, then sends readers to the individual components for documentation and source code. Nothing in the file list contradicts that: there is no src directory, and no loop implementation sits at the top level.
.gitattributes
.github/
.gitignore
composer.json
phpunit.xml.dist
phpunit.xml.legacy
tests/Cloning gets you documentation, a package manifest, two phpunit configurations and a tests folder, and not one file that dispatches I/O readiness. In practice a decision about this repository is a decision about a dozen separate packages.
Cadence at the index itself is thin and dated: v1.4.0 landed on 2023-07-11, v1.3.0 on 2022-07-11 and v1.2.0 on 2021-07-11, the same calendar day three years running. The last push was on 2026-10-06, and the default branch is 1.x. Whether a given component moved in that window is a question each component repository answers on its own.
Non-blocking by default, so blocking work needs workers
ReactPHP is non-blocking by default, and the README answers the obvious objection in one line: use workers for blocking I/O. That single sentence is the whole operational contract. A loop that never blocks on a read cannot run a blocking database driver in the same process, so any call waiting on a file descriptor you never registered has to move somewhere else.
Internally the loop follows the reactor pattern, which is where the name comes from, and the README calls it strongly inspired by EventMachine in Ruby, Twisted in Python and Node.js. Its stated design goal is cooperative multitasking inside a single PHP process, aimed at servers handling hundreds or thousands of concurrent connections rather than at speeding up one request.
Two consequences follow from that shape. Time spent inside a PHP callback still stalls the loop for every connection that process owns, so a CPU-heavy job is not made cheaper by being non-blocking. Back-pressure, with no thread to hide behind, has to be handled by the stream and promise layer rather than by the operating system.
The bundled example never mentions installing this repository
No install step exists for reactphp/reactphp itself. The Hello World server in the README gives its own comment lines, and both point at other packages.
<?php
// $ composer require react/http react/socket # install example using Composer
// $ php example.php # run example on command line, requires no additional web server
require __DIR__ . '/vendor/autoload.php';That is the whole first-use tutorial, and its silence is the detail worth noticing: a reader looking for how to install this PHP library is never told to run composer require on it. Next the example builds a `React\Http\HttpServer`, binds it to a `React\Socket\SocketServer` on 127.0.0.1:8080 and prints the address it serves.
$server = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
return React\Http\Message\Response::plaintext(
"Hello World!\n"
);
});
$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$server->listen($socket);The signatures show the layering the family rests on: a PSR-7 server request arrives, a PSR-7 response goes back, and the transport underneath is a socket object instead of a web server. Expect one line naming the listening address, then silence until you interrupt it. Rollback, upgrade paths between major lines and configuration are not documented here, because there is nothing here to configure.
Four core components, then nine more with separate homes
The index splits the family into three groups, and the split tells you where a given behaviour actually lives. The core group holds EventLoop, described as the reactor event loop, Stream for event-driven readable and writable streams, Promise as a Promises/A implementation, and Async as async utilities and fibers.
The network group adds Socket for plaintext TCP/IP and TLS servers and clients, Datagram for event-driven UDP client and server sockets, HTTP for a streaming HTTP client and server, and DNS as an async resolver. Utility packages carry Cache for async caching, ChildProcess for executing child processes, PromiseTimer, and PromiseStream, described as the link between promise-land and stream-land.
Each entry links to a separate repository with its own documentation, which is the practical payoff: you can take Stream without the HTTP server, or Promise alone. Credit goes in the README to decoupled parts that can be replaced by alternate implementations, and to standard PSRs where possible for interoperability. Both are architectural claims, not switches you can flip.
Promises and streams meet in one adapter package
Two abstractions carry most of the weight, and a dedicated package exists purely to join them. Stream provides event-driven readable and writable streams for non-blocking I/O, while Promise is a Promises/A implementation for PHP. Between them sits PromiseStream, called in the index the missing link between Promise-land and Stream-land, built on top of ReactPHP. Timeouts get their own package as well, PromiseTimer, described as a trivial timeout implementation for ReactPHP's Promise lib.
Async adds async utilities and fibers on top of that base, giving a callback-style codebase a second way to express sequencing. Around the same core sit Datagram for UDP client and server sockets, DNS as an async resolver, Cache for async caching, and ChildProcess for executing child processes, which is the sanctioned route for the blocking work that has to leave the loop.
Nowhere in the index is there a word on how a running loop is selected or attached to the process, and no configuration file is offered. Choosing between implementations is left to the component repositories, along with the PHP version each one requires.
PHP 7+ for speed, PHP 5.3 and HHVM for compatibility
Here the index contradicts itself in adjacent bullets. One says it highly recommends the latest version of PHP 7+ for best performance and support. The very next says it supports legacy PHP 5.3+ and HHVM for maximum compatibility. Two different version floors for one codebase, with no note reconciling them.
The file list carries the same split: beside phpunit.xml.dist there is a separate phpunit.xml.legacy. Two test configurations in one repository is what holding a legacy floor costs in practice, and it is the clearest evidence that the compatibility claim is not a passing remark. Make the call against the component repository's own requirement rather than against this README.
A second tension sits in the extension story. One bullet says ReactPHP requires no extensions and runs on any platform with the phrase no excuses attached; another says it takes advantage of optional extensions to get better performance when available. Neither is false, but the first tells a reader nothing about the speed difference being bought when such an extension is present. No list of qualifying extensions and no figures for the difference appear anywhere.
Non-blocking suits idle connections, not CPU-bound work
The failure mode is not a bug, it is the design. Every connection in a process shares one loop, so a single slow or CPU-bound callback delays all the others that process serves. The README's own targets, hundreds or thousands of concurrent connections plus long-running applications, describe workloads where sockets sit idle. A request that spends its life on computation falls outside what the loop covers.
The same holds for I/O the loop cannot observe. The answer on offer is workers, which drags in process management, IPC and supervision that the README never describes. No threshold is given for when a worker count becomes necessary, and no guidance covers sharing state between the loop process and those workers.
Against the libraries named as inspirations, the difference is ownership of the runtime: EventMachine, Twisted and Node.js ship their own event loop and I/O selector, while ReactPHP builds the same pattern on PHP's own stream functions with an optional loop implementation. A codebase already full of blocking libraries or a synchronous ORM needs adapters, and the README does not document which exist. Its ecosystem list, from Ratchet for WebSocket servers to PPM as a process manager for modern PHP applications and Predis\Async for Redis, shows what has been built on top, but each of those is a separate project.
Editorial conclusion
Adopt ReactPHP when one process has to hold many idle-open TCP or HTTP connections and your team can write against Promises/A instead of blocking calls. Do not adopt it to speed up CPU-bound PHP, and do not treat this repository as the library itself, since cloning it yields a README, a composer.json and two phpunit configs with no src directory in sight. Before anything else, check the component repository you actually depend on, because this index delegates every detail about streams, promises, DNS and HTTP to those separate repos.
Frequently asked questions
How do I install ReactPHP?
The README gives no install command for this repository. Its example installs the pieces it uses with `composer require react/http react/socket`, then runs the file with `php example.php` and no additional web server.
What is the difference between ReactPHP and Node.js or Twisted?
The README says the loop follows the reactor pattern and is strongly inspired by EventMachine, Twisted and Node.js. Those projects own their runtime and I/O selector, while ReactPHP builds the pattern on PHP with an optional event loop implementation.
Does ReactPHP support PHP 5.3 and HHVM?
The README states that it supports legacy PHP 5.3+ and HHVM, while also stating that it highly recommends the latest version of PHP 7+. The two bullets sit next to each other and no note reconciles them.
Do I need any PHP extensions to use ReactPHP?
The README says ReactPHP requires no extensions and runs on any platform. It also says it takes advantage of optional extensions for better performance when available, without naming them or quantifying the difference.
Can ReactPHP handle blocking database calls?
ReactPHP is non-blocking by default and the README says to use workers for blocking I/O. It documents no worker threshold, no IPC mechanism and no list of blocking libraries with adapters.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/reactphp-reactphp)