Coroutine extension and server12 min read

Open Swoole: a coroutine extension and server for PHP

A guide to Open Swoole, a C/C++ PHP extension and server that keeps PHP code resident, with a minimal loopback HTTP server and notes on state leakage.

PHP compatibility and project lifecycle

Compatibility is unknown from the supplied source. The page shows a PECL and Composer version line but is marked last updated February 9, 2023. It gives no PHP 8.4 or 8.5 support statement, no license and no support policy. Verify against the official site before use.

Official sources checked 2026-10-22. Browser lessons on this site run PHP 8.5.

What this project is

Open Swoole is described in its official documentation as a high-performance network framework built on an event-driven, asynchronous, non-blocking I/O coroutine model for PHP. It is written in C/C++ and installed as a PHP extension. Its documented goal is to let PHP developers write concurrent TCP, UDP, Unix socket, HTTP, WebSocket and FastCGI services in PHP syntax, using coroutines so that asynchronous code can be written in a synchronous style.

It is based only on the single official documentation page supplied, and nothing here has been executed.

Classification

Open Swoole is not a standalone PHP runtime and not a replacement interpreter. It is an extension that loads into an ordinary PHP installation, and the documentation says it runs as a PHP CLI application. The PHP language and its core still come from PHP itself. Open Swoole adds a server, an event loop, coroutines and multiprocessing primitives on top.

It is also not a CMS and not a full-stack framework. It is infrastructure that frameworks or applications could sit on. The documentation mentions CMS platforms as something you can build. It gives no setup steps for any specific framework or CMS, so this guide does not invent any. If you want to run a framework or CMS product on it, follow that product's own official documentation. Framework components, CMS products such as Drupal, and PHP core are three separate things.

Open Swoole versus Swoole

Open Swoole is a project and namespace distinct from Swoole. The documented example uses classes under the OpenSwoole namespace, such as OpenSwoole\Http\Server. The navigation also lists an Open Swoole Class Alias page, but its content is not in the supplied material. How the two projects relate, and whether code or extensions are interchangeable, is unknown from this source. Do not assume it. Do not load both extensions in one environment without reading the official guidance.

Architecture

The documentation lists these components: the OpenSwoole extension, OpenSwoole Core, OpenSwoole Psr (provided within Core), OpenSwoole GRPC, an IDE helper and a dashboard. The documented feature areas are:

  • servers for TCP/UDP, HTTP, WebSocket, MQTT and gRPC
  • an event loop API and timers
  • coroutines, channels, wait groups, hooks and context
  • coroutine clients for TCP/UDP, HTTP, HTTP/2, sockets, FastCGI, Redis, MySQL and Postgres
  • multiprocessing: processes, process pools, tables, atomics and locks

Execution model

In classic PHP deployments, each request starts a fresh request lifetime and discards its state at the end. The documentation says Open Swoole moves you out of this traditional stateless model. You start a long-running server process, and a callback handles each request. The documented example registers a start handler and a request handler, then calls start.

That makes it a persistent-worker model. Code loaded at startup stays in memory, and the same process serves many requests. Concurrency comes from coroutines inside the event loop. The documentation also describes task workers and process pools. How many workers run by default, and how they are managed, is not stated in the supplied material, so check the server pages before relying on any assumption.

State leakage and cleanup

Because a worker outlives a single request, anything stored in a global variable, static property, singleton, long-lived container or in-memory cache can carry over to the next request. Typical leaks:

  • user or tenant data kept in a shared object
  • request-specific settings written to static state
  • connections or transactions left open
  • caches that grow without bound

Practical cleanup habits:

  • Keep per-request data in local variables or objects created inside the request handler.
  • Treat static and global state as read-only after startup.
  • Reset or avoid shared singletons that hold request data.
  • Close or return connections and release resources at the end of each request.
  • Be careful when coroutines run concurrently in one worker: shared mutable state can interleave between them. The documentation lists a coroutine context feature, so read that page for per-coroutine storage.
  • Watch memory over time, and test with repeated requests as different users.

Some state is intentionally shared across processes, through the documented Table, Atomic and Lock features. Treat these as explicit shared state with their own rules.

Practical use cases

The documentation names web servers, API backends, game servers, chat systems, microservices and realtime services. Fits include long-lived WebSocket connections, services that wait on many network calls at once, and custom TCP or UDP protocols. A conventional page-rendering app with no concurrency need may gain little from the extra operational care.

Installation approach

The page shows a latest-version line with a PECL command and a Composer command for the core package. The page also says it was last updated on February 9, 2023, so whether that version is current is unknown. Check the official site before installing. Compatibility with PHP 8.4 or 8.5, the license and the support status are not given in the supplied material, so they are unknown.

The approach is to install the extension with PECL into a PHP CLI, confirm it loads, and optionally add the core package with Composer. The first example needs only the extension. No official Docker image or tag appears in the source, so none is used. Enable the extension in whatever way suits your PHP installation.

Strengths

  • Coroutines let you write concurrent code in a synchronous style.
  • Servers for several protocols are built in.
  • Coroutine clients cover common services, and existing PHP libraries can be used.
  • It supports multiprocessing and shared-memory primitives.

Limitations

  • It is a native extension, so installation is more involved than a Composer-only library.
  • Persistent workers require deliberate state management.
  • Compatibility, licensing, support status and performance figures are not established by the source, so none are claimed.
  • Framework and CMS integration is not covered by this source.
  • Runtime examples need a PHP CLI with the extension and are not browser exercises.

Deployment

The documentation says you can run an Open Swoole HTTP server directly on your network, or place Apache or Nginx in front with a proxy pass. For development, bind to 127.0.0.1 as the examples do. Never expose FastCGI services publicly. Process supervision, reload behavior and tuning options are unknown from this source, so consult the server documentation.

Examples in this guide

The first example is the documented hello world server on the loopback address. The second adds a per-process counter to make persistent state visible.

Links

The official documentation is linked below, and it is the only source used for this guide.

Practical examples

These examples have not been run in a live environment yet. Commands and versions follow the official documentation linked on this page; check them before relying on them, and report a problem if one does not work.

Minimal Open Swoole HTTP server on loopback

Adapts the hello world HTTP server from the official documentation. It is a single PHP CLI script bound to 127.0.0.1:9501, so it is reachable only from the local machine. It requires a PHP CLI with the OpenSwoole extension installed through PECL. It is not a browser exercise.

server.php

<?php

use OpenSwoole\Http\Server;
use OpenSwoole\Http\Request;
use OpenSwoole\Http\Response;

$server = new Server('127.0.0.1', 9501);

$server->on('start', function (Server $server) {
    echo "OpenSwoole http server is started at http://127.0.0.1:9501\n";
});

$server->on('request', function (Request $request, Response $response) {
    $response->header('Content-Type', 'text/plain');
    $response->end("Hello World\n");
});

$server->start();

Install and run

pecl install openswoole-26.2.0
php -m
php server.php
curl http://127.0.0.1:9501/

Expected behavior

The php -m listing should include an openswoole entry once the extension is enabled. Running php server.php prints the start message and keeps the process running in the foreground. The curl request should return the text Hello World with a text/plain content type. Stop the server with Ctrl+C in its terminal.

Requires a PHP CLI with a compiler toolchain for PECL. PHP 8.4 compatibility is unknown from the source, and the version string comes from a page last updated in 2023. The extension may need to be enabled manually in your PHP configuration. There is no TLS, proxy or process supervision. This is a development-only example.

Persistent worker counter showing retained state

Extends the minimal server with a variable that survives across requests, to show that a worker keeps memory between requests. It uses only the classes and methods in the official hello world. It requires the same extension setup and is not a browser exercise.

counter-server.php

<?php

use OpenSwoole\Http\Server;
use OpenSwoole\Http\Request;
use OpenSwoole\Http\Response;

$server = new Server('127.0.0.1', 9501);

// Declared once at startup. Whether it is shared depends on worker processes.
$count = 0;

$server->on('start', function (Server $server) {
    echo "Counter server started at http://127.0.0.1:9501\n";
});

$server->on('request', function (Request $request, Response $response) use (&$count) {
    $count++;
    $response->header('Content-Type', 'text/plain');
    $response->end('Requests seen by this worker process: ' . $count . "\n");
});

$server->start();

Install and run

php counter-server.php
curl http://127.0.0.1:9501/
curl http://127.0.0.1:9501/

Expected behavior

Each curl call should report a higher number than the previous one, because the worker process keeps the variable in memory between requests. A classic per-request PHP setup would reset it each time. If the server runs several worker processes, the counts may differ between responses, since each worker holds its own copy.

The default number of workers is not stated in the supplied source, so exact numbers are not guaranteed. This is a teaching demonstration of state retention, not a pattern to copy. Real applications should keep request data out of shared state.