OpenSwoole: The PHP That Stays Alive Between Requests
Discover why OpenSwoole is much more than a performance tool. Learn how it completely changes the lifecycle of PHP applications and what developers need to keep in mind when using it.
Table of Contents
Most PHP developers write code based on one fundamental assumption:
"Once the response is sent to the browser, the entire application state disappears."
With OpenSwoole, that assumption is no longer true.
For decades, PHP has been known for its incredibly simple execution model: a request arrives, the script runs, and once the response is sent, all the memory used during execution is discarded.
This behavior became part of the language's identity and directly influenced how millions of applications were built. Frameworks, libraries, and even design patterns assume that every request starts with a completely clean environment.
However, this model comes at a cost.
For every single request, PHP must:
- Initialize the application.
- Load classes.
- Establish connections.
- Build the dependency injection container.
- Execute the entire bootstrap process again.
Even with technologies like OPcache reducing part of this overhead, rebuilding the application environment thousands of times per second still carries a significant performance cost.
This is exactly the paradigm that OpenSwoole aims to change.
Instead of executing a script from start to finish for every request, OpenSwoole keeps a PHP server running continuously. The application is initialized only once and remains alive, ready to handle thousands of consecutive requests.
But the benefits go far beyond performance.
By changing the application's lifecycle, OpenSwoole also changes how developers must think about state, memory, concurrency, and application architecture.
In this article, we'll explore how OpenSwoole works and why this shift in execution model requires considerations that simply don't exist in traditional PHP.
How Traditional PHP Works
In a traditional PHP environment (Apache + mod_php, PHP-FPM, or CGI), every request is completely independent from the others.
Imagine a user visiting a page:
Client
│
▼
PHP starts
│
Loads the autoloader
│
Bootstraps the framework
│
Executes your code
│
Sends the response
│
Releases all memory
Once the response is sent back to the browser, almost everything is destroyed.
This means that:
- Objects cease to exist.
- Variables are discarded.
- Singletons disappear.
- The dependency injection container is destroyed.
- All allocated memory is released.
When the next request arrives, the entire process starts over from scratch.
This execution model is precisely what makes certain coding patterns naturally safe.
For example:
class RequestCounter
{
private int $count = 0;
public function increment(): int
{
return ++$this->count;
}
}
$counter = new RequestCounter();
echo $counter->increment();
No matter how many times the user refreshes the page, the output will always be:
1
That's because a brand-new object is created for every request.
Here's another example:
class Cache
{
private array $items = [];
public function put(string $key, mixed $value): void
{
$this->items[$key] = $value;
}
public function get(string $key): mixed
{
return $this->items[$key] ?? null;
}
}
In traditional PHP, this cache exists only for the lifetime of the current request.
As soon as the response is sent, everything disappears.
For this reason, PHP developers have spent decades without having to worry about persistent memory or state leaking between requests.
What Changes with OpenSwoole
OpenSwoole completely changes this execution model.
Instead of running a PHP script for every incoming request, it starts a server that remains running continuously.
The execution flow now looks something like this:
Server starts
│
Loads Composer
│
Bootstraps the framework
│
Creates objects
│
────────────────────────────
│
Request 1
│
Request 2
│
Request 3
│
Request 4
│
...
Notice that the application is no longer rebuilt for every request.
Instead, it stays alive in memory.
This means that objects created during the application's startup continue to exist until the server is restarted or the worker process is recycled.
A simple example makes this difference easier to understand.
<?php
$counter = 0;
$server = new OpenSwoole\Http\Server('127.0.0.1', 9501);
$server->on('request', function ($request, $response) use (&$counter) {
$counter++;
$response->end("Request number {$counter}");
});
$server->start();
If you visit:
http://localhost:9501
The first response will be:
Request number 1
Refresh the page:
Request number 2
Refresh it again:
Request number 3
This would be impossible in traditional PHP using a regular variable.
The variable would be destroyed at the end of every request.
With OpenSwoole, however, it remains in memory.
This persistent execution model is what dramatically reduces the time spent bootstrapping your application.
At the same time, it introduces a new responsibility: making sure that data from one request cannot accidentally leak into another.
That's why applications built with OpenSwoole need to be especially careful with:
- static properties;
- stateful singletons;
- global variables;
- in-memory caches;
- reused objects.
These elements are no longer limited to a single request—they remain alive for as long as the process is running.
Installing OpenSwoole
OpenSwoole is distributed as a native PHP extension, so installing it through Composer is not enough.
The most common installation method is through PECL:
pecl install openswoole
Next, enable the extension in your php.ini:
extension=openswoole
You can verify that the installation was successful by running:
php -m | grep openswoole
Or:
php --ri openswoole
If the extension is loaded correctly, PHP will display information such as the installed version, enabled features, and compilation options.
Building an HTTP Server in Just a Few Lines
Once the extension is installed, creating an HTTP server is surprisingly simple:
<?php
use OpenSwoole\Http\Request;
use OpenSwoole\Http\Response;
use OpenSwoole\Http\Server;
$server = new Server('127.0.0.1', 9501);
$server->on('request', function (
Request $request,
Response $response
) {
$response->header('Content-Type', 'text/plain');
$response->end("Hello, OpenSwoole!");
});
$server->start();
Run the script as usual:
php server.php
The terminal will remain occupied because your script is now running as a fully functional HTTP server.
Simply open:
http://127.0.0.1:9501
And you'll see:
Hello, OpenSwoole!
This small example already demonstrates the biggest difference compared to traditional PHP: the script does not terminate after serving a request. Instead, it keeps running, waiting for the next connection.
This persistent execution model is what enables OpenSwoole to provide powerful features such as coroutines, WebSockets, timers, asynchronous tasks, and significantly higher performance than the traditional process-per-request model.
The Mistake Almost Everyone Makes
When developers first start using OpenSwoole, they usually continue writing PHP the same way they always have. After all, it's still PHP, the framework may be the same, and most of the code continues to work just fine.
The problem is that some practices that were perfectly safe in traditional PHP are no longer safe.
The most common mistake is assuming that objects remain isolated between requests.
Consider the following service:
class UserService
{
private ?User $currentUser = null;
public function setUser(User $user): void
{
$this->currentUser = $user;
}
public function getCurrentUser(): ?User
{
return $this->currentUser;
}
}
In traditional PHP, this rarely causes any problems.
A new object is created for every request and destroyed once execution finishes.
With OpenSwoole, however, that object may continue to live in memory.
Imagine the following sequence:
Request A
────────────
$currentUser = John
↓
Response sent
↓
Object remains alive
Request B
────────────
$currentUser = ?
If this service is shared across multiple requests—for example, as a singleton—the next user may unexpectedly receive data belonging to the previous one.
This type of issue is known as state leakage.
Another common example involves static properties:
class Counter
{
public static int $requests = 0;
}
Counter::$requests++;
echo Counter::$requests;
In traditional PHP, the output will always be:
1
With OpenSwoole, however, it becomes:
1
2
3
4
5
...
The static property is never reset between requests.
The same caution applies to:
- global variables;
- array-based in-memory caches;
- objects stored in singletons;
- improperly shared database connections;
- any structure that keeps state in memory.
This doesn't mean these techniques are forbidden.
It simply means they now behave exactly as they're designed to: they remain alive.
Another important aspect is that OpenSwoole can process multiple requests concurrently using coroutines. Although coroutines are much lighter than operating system threads, two coroutines can still access the same shared object simultaneously if it isn't designed for concurrent use.
In other words, OpenSwoole brings PHP much closer to the execution model used by platforms like Java, Go, .NET, and Node.js, where applications remain running for long periods and memory management requires much greater attention.
Is OpenSwoole Dangerous?
Not at all.
What it actually does is remove a "safety net" that traditional PHP provided automatically.
For many years, PHP's short-lived request lifecycle masked countless architectural issues. Since everything was destroyed at the end of each request, it was almost impossible for an object to live long enough to produce unintended side effects.
With OpenSwoole, that's no longer the case.
But that's not a flaw.
It's simply how applications have worked for years in platforms such as:
- Java (Spring Boot);
- ASP.NET;
- Go;
- Node.js;
- Rust (Axum, Actix, and others).
None of these platforms rebuild the entire application for every request.
With OpenSwoole, PHP simply adopts the same execution model.
In practice, following a few good practices is enough:
- Avoid storing request-specific data in shared objects.
- Prefer stateless services whenever possible.
- Keep request-specific information in local variables.
- Don't overuse static properties.
- Share only resources that are truly meant to be shared, such as connection pools, global caches, and application configuration.
Modern frameworks also help significantly. Projects like Laravel Octane have been specifically adapted to run on top of OpenSwoole, taking numerous internal precautions to prevent state leakage.
Ultimately, OpenSwoole doesn't make your application more fragile.
It simply requires the same architectural discipline that developers working with other server-side platforms have embraced for years.
What Do You Get in Return?
This shift in execution model brings benefits that go far beyond reducing response times.
Because the application stays loaded in memory, the startup cost virtually disappears.
Instead of rebuilding the entire framework for every request, the server simply reuses the already initialized environment.
This significantly reduces the repetitive work PHP has to perform.
On top of that, OpenSwoole provides features that would typically require additional tools or much more complex architectures.
Coroutines
Coroutines allow I/O-bound operations to run concurrently without creating multiple operating system threads.
Imagine an API that needs to query three external services.
With traditional PHP:
API A → waiting
↓
API B → waiting
↓
API C → waiting
With coroutines:
API A ─┐
├── execute concurrently
API B ─┤
│
API C ─┘
In practice:
use OpenSwoole\Coroutine;
Coroutine::run(function () {
Coroutine::create(function () {
echo "Calling API A...\n";
});
Coroutine::create(function () {
echo "Calling API B...\n";
});
Coroutine::create(function () {
echo "Calling API C...\n";
});
});
Although this example simply prints messages, in a real-world application each coroutine could perform an HTTP request, execute a database query, or communicate with another service. Since these operations are primarily I/O-bound, running them concurrently can significantly reduce the total execution time.
Native WebSockets
Building WebSocket servers becomes remarkably straightforward.
This makes it easy to develop real-time applications such as:
- chat systems;
- live notifications;
- dashboards;
- online games;
- system monitoring;
- collaborative editing tools.
All without introducing dedicated WebSocket servers into your infrastructure.
High-Performance HTTP Server
OpenSwoole includes its own highly optimized HTTP server.
Instead of relying on PHP-FPM to handle incoming requests, your application can run directly on OpenSwoole's event-driven server, reducing the overhead associated with the traditional process-per-request model.
Timers
You can also schedule recurring tasks directly inside your application.
For example:
use OpenSwoole\Timer;
Timer::tick(5000, function () {
echo "Running every 5 seconds...\n";
});
This feature is useful for:
- clearing caches;
- synchronizing data;
- collecting metrics;
- processing queues;
- monitoring system resources.
All without depending on external cron jobs.
Asynchronous Background Tasks
OpenSwoole also simplifies the creation of workers and background tasks.
This makes it easy to offload time-consuming operations, such as:
- sending emails;
- generating PDFs;
- processing images;
- importing files;
- integrating with third-party APIs.
Meanwhile, users receive a response immediately instead of waiting for those operations to finish.
Better Hardware Utilization
Because coroutines are extremely lightweight, a single process can efficiently handle thousands of concurrent connections.
This reduces the number of processes required to serve a large number of users while making much better use of CPU and memory resources—especially in applications dominated by I/O operations.
Ultimately, this may be OpenSwoole's greatest advantage: it transforms PHP into a platform capable of running modern, highly concurrent, long-lived applications without sacrificing the simplicity and productivity that made the language so popular.
It doesn't replace traditional PHP in every scenario, but it dramatically expands the range of problems PHP can solve efficiently.
Conclusion
For many years, PHP has been associated with a simple execution model: receive a request, execute the code, send the response, and terminate the process. This model made development intuitive and played a major role in PHP's widespread adoption, but it also established assumptions that many developers came to see as fundamental.
OpenSwoole challenges one of those assumptions.
By keeping the application alive in memory, it eliminates much of the startup overhead, provides powerful features such as coroutines, WebSockets, timers, and asynchronous processing, and enables PHP applications to achieve levels of performance and concurrency that were once associated only with other platforms.
At the same time, this new execution model requires a different mindset. Objects are no longer discarded after each request, state can persist in memory, and architectural best practices become even more important.
The good news is that this isn't a new concept in software development. Platforms like Java, Go, .NET, and Node.js have worked this way for years. OpenSwoole simply brings PHP into the same category while preserving the language, syntax, and ecosystem that developers already know.
That doesn't mean OpenSwoole should replace PHP-FPM or Apache in every application. Many projects will continue to perform perfectly well using the traditional request lifecycle. However, if you're building high-performance APIs, real-time systems, or applications that must handle thousands of simultaneous connections, OpenSwoole becomes an incredibly compelling option.
In the end, learning OpenSwoole isn't just about mastering another PHP extension.
It's about embracing a different execution model and realizing that modern PHP has evolved far beyond the traditional "run and exit" lifecycle.
If you want to unlock the full potential of today's PHP ecosystem, OpenSwoole is well worth exploring.
Learning OpenSwoole isn't just about learning another library.
It's about letting go of an assumption that has shaped PHP since the 1990s.
And perhaps that's exactly what makes it one of the most fascinating technologies in the modern PHP ecosystem.