PHP was designed for the request-response model: a request arrives, PHP processes it, sends a response, and the process dies. This model is simple and eliminates entire categories of bugs around state management. But it also means every request pays the cost of bootstrapping the application, and concurrent I/O requires awkward workarounds.
Swoole changes this by turning PHP into a long-running process with coroutine-based concurrency. Your PHP code can now handle thousands of concurrent connections, run parallel database queries, and serve WebSocket connections—all from a single process.
What Swoole provides
Swoole is a PHP extension (written in C++) that adds:
- Coroutines: Lightweight green threads that yield during I/O
- Async I/O: Non-blocking database, HTTP, file, and Redis clients
- HTTP server: Replaces Nginx + php-fpm entirely
- WebSocket server: Native WebSocket support
- Task workers: Offload heavy computation without blocking the event loop
- Connection pooling: Reuse database and Redis connections across requests
Installation
1 | # Via PECL |
Add to php.ini:
1 | extension=swoole |
Coroutines: the core concept
A coroutine is a function that can pause execution while waiting for I/O and resume when the I/O completes. This is different from threading—coroutines share a single thread and switch cooperatively.
1 | use Swoole\Coroutine; |
Both HTTP requests happen concurrently. When one coroutine is waiting for a network response, the other runs. Total time is roughly equal to the slowest request, not the sum of both.
How this differs from JavaScript async/await
In JavaScript, you explicitly await promises. In Swoole, I/O functions automatically yield the coroutine. You write synchronous-looking code, and Swoole makes it concurrent:
1 | // This looks synchronous but is actually concurrent under Swoole |
Under php-fpm, those two queries run sequentially. Under Swoole, if you wrap them in separate coroutines, they run concurrently.
Building an HTTP server
1 | use Swoole\Http\Server; |
This server handles thousands of concurrent connections on a single machine. Each request runs in a coroutine, so I/O-bound operations (database queries, external API calls) do not block other requests.
Connection pooling
Without pooling, each coroutine opens a new database connection. With 1,000 concurrent requests, you would exhaust MySQL’s connection limit.
1 | use Swoole\Database\PDOConfig; |
With Laravel Octane
Laravel Octane manages connection pooling automatically:
1 | php artisan octane:start --server=swoole --workers=4 --task-workers=6 |
Octane resets the application state between requests and manages connection lifecycle. This is the recommended approach for Laravel projects.
WebSocket server
1 | use Swoole\WebSocket\Server; |
This is a complete WebSocket chat server in PHP. No Node.js, no external dependencies.
Common mistakes
Not resetting state between requests: Static variables, global state, and class-level caches persist across requests in Swoole. If you store a user object in a static property during request #1, it is still there during request #2.
1 | // BUG: state leaks between requests |
Using blocking I/O libraries: Standard PHP functions like file_get_contents work but block the event loop when used outside coroutine context. Use Swoole’s coroutine clients or wrap blocking calls in Coroutine::create().
Ignoring memory leaks: In php-fpm, memory leaks do not matter because the process dies after each request. In Swoole, a process handles thousands of requests. Small leaks accumulate. Use max_request to periodically restart workers.
Production deployment
1 | # docker-compose.yml |
Monitoring
Monitor these metrics in production:
- Coroutine count (should not grow unbounded)
- Connection pool utilization
- Worker memory usage over time
- Request processing time percentiles
When to choose Swoole vs. alternatives
| Need | Swoole | FrankenPHP | php-fpm | ReactPHP |
|---|---|---|---|---|
| High concurrency | ✅ Best | Good | Adequate | Good |
| WebSockets | ✅ Native | No | No | ✅ Native |
| Framework support | Laravel, Symfony | Laravel | All | Limited |
| Learning curve | Steep | Moderate | None | Moderate |
| Hosting flexibility | VPS/container only | VPS/container | Everywhere | VPS/container |
FAQ
Can I use Swoole with WordPress?
Not practically. WordPress relies heavily on global state and blocking I/O patterns that conflict with Swoole’s coroutine model.
Is Swoole or OpenSwoole better?
Swoole (upstream) has more active development and wider community support as of 2026. OpenSwoole diverged in 2021 and has a different roadmap. Choose based on which is more actively maintained when you evaluate.
Do I need to rewrite my application for Swoole?
If you use Laravel Octane, no. Octane handles the adaptation layer. For custom applications, you need to audit state management and replace blocking I/O calls.
Next steps
Start with Laravel Octane + Swoole if you are on Laravel. For other frameworks, install the Swoole extension and build a minimal HTTP server to understand coroutine behavior before porting your application.
The FrankenPHP guide covers an alternative high-performance runtime that is easier to adopt. For API design patterns that benefit from Swoole’s concurrency, see the REST API best practices guide.