Swoole & Async PHP
debt(d9/e7/b9/t7)
Closest to 'silent in production until users hit it' (d9). detection_hints.automated is no; blocking calls in coroutines won't error — they just serialize all execution and surface as production latency under load.
Closest to 'cross-cutting refactor across the codebase' (e7). quick_fix requires swapping PDO for Swoole-native clients, introducing connection pools, and adopting channels — this touches every I/O site across the app, not a one-line fix.
Closest to 'defines the system's shape' (b9). Choosing Swoole/async PHP shapes the entire runtime model (persistent processes, coroutines, no shared-nothing FPM assumptions); applies_to cli/queue-worker contexts and every library choice must be coroutine-safe — rewrite-or-live-with-it.
Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The misconception (Swoole as framework vs extension) plus the FPM-style assumption that memory resets per request is contradicted by persistent processes — competent PHP devs guess wrong because it violates the shared-nothing mental model they've used for decades.
TL;DR
Explanation
Swoole replaces PHP-FPM with a persistent process server. Coroutines (go() function) run cooperatively — they yield on I/O automatically. Built-in: async MySQL/Redis/HTTP client, connection pools, timers, WebSocket. Coroutines share heap — race conditions possible on shared variables. Swoole\Coroutine\Channel for inter-coroutine communication. Benefits: 10–100x throughput improvement for I/O-bound workloads. Cost: different programming model, non-Swoole-aware libraries block. Laravel Octane integrates Swoole transparently. PHP 8.1 Fibers provide similar primitives without Swoole.
Common Misconception
Why It Matters
Common Mistakes
- Using blocking libraries (standard PDO) in Swoole coroutines — blocks all coroutines.
- Sharing mutable state between coroutines without channels or locks.
- Not understanding that Swoole processes are persistent — memory leaks matter more than in FPM.
Code Examples
// Blocking PDO in Swoole coroutine — kills throughput:
go(function() {
$pdo = new PDO($dsn); // Blocking — suspends all coroutines
$pdo->query('SELECT sleep(1)');
});
// Swoole async MySQL:
go(function() {
$pool = new Swoole\Database\PDOPool(new Swoole\Database\PDOConfig());
$pdo = $pool->get();
$result = $pdo->query('SELECT * FROM users');
$pool->put($pdo);
});