DEV Community

Roman Shneer
Roman Shneer

Posted on

PHP is 5x Faster Than NestJS? Rethinking High-Load with Swoole.

For years, the industry consensus was clear: if you need high concurrency, non-blocking I/O, and microservices, you choose Node.js (NestJS) or Go. PHP was labeled as the "old-school" language, hindered by its "request-response" lifecycle and the overhead of booting the framework for every single hit.

I decided to challenge that stereotype.

I built a production-ready High-Load Event Processor capable of handling 10,000+ RPS using PHP 8.4 and Swoole. In my stress tests, this architecture consistently outperformed equivalent NestJS setups by nearly 5x in throughput, while maintaining a significantly lower latency floor.

The Problem with the Status Quo

Traditional PHP (FPM) is like a restaurant that hires and fires its entire staff every time a customer walks in. It’s reliable but inefficient for high-frequency event ingestion. Node.js improved this with a persistent event loop, but even the V8 engine has its limits when managing tens of thousands of concurrent Promises.

Why Swoole Changes Everything

Swoole isn't just a library; it’s a C-native coroutine engine that transforms PHP into a high-performance, persistent-memory powerhouse. Here is why it crushed the competition in my benchmarks:

1. C-Native Coroutines vs. The Event Loop
While NestJS relies on the JavaScript Event Loop and async/await overhead, Swoole introduces user-space threads (coroutines) managed at the C level. Context switching happens only during I/O operations, with far less CPU overhead than managing the Promise lifecycle in V8.

2. Persistent State & Zero Cold Starts
The application boots once. Database connections, configurations, and pre-compiled code stay in memory. This eliminates the "bootstrap tax" and allows for lightning-fast execution.

3. Native Connection Pooling
One of the biggest bottlenecks in high-load systems is the database. In my project, I implemented Swoole-native Connection Pooling for PostgreSQL and Redis. Unlike standard Node.js drivers that can struggle under extreme concurrency, Swoole handles thousands of active connections with minimal memory footprint.

The Architecture: 10,000 Requests Per Second

My system uses a multi-layered approach to ensure Zero Data Loss:

  • Ingestion: A Swoole HTTP server receives events and pushes them into a Redis buffer using non-blocking coroutines.
  • Buffering: Redis acts as a high-speed shock absorber for traffic spikes.
  • Processing: Dedicated workers pull batches from Redis and persist them to PostgreSQL using optimized write-pipelines.

The Results

Using Artillery for load testing, the results were undeniable:

  • Throughput: Stable 10k+ RPS on standard hardware.
  • Latency: p95 remained flat even as concurrency scaled.
  • Reliability: 0% packet loss, thanks to the asynchronous pipeline.

Conclusion: Is PHP Back?

PHP never left, but it has evolved. With Swoole, we no longer have to trade the rapid development cycle of PHP for the performance of Go or Node.js. We can have both.

If you are building microservices in 2026 and performance is your priority, it’s time to stop looking at PHP in the rearview mirror and start looking at what it can do with Swoole.

PHP stress test

artillery run performance/main.yml
Enter fullscreen mode Exit fullscreen mode

PHP/Swoole artillery - stress test

NestJS stress test

artillery run performance/main.yml
Enter fullscreen mode Exit fullscreen mode

NestJS artillery - stress test

PHP/Swoole Insert 1million records

artillery run performance/insert1m.yml
Enter fullscreen mode Exit fullscreen mode

PHP/Swoole artillery - Insert 1million records test

NestJs Insert 1 million records

artillery run performance/insert1m.yml
Enter fullscreen mode Exit fullscreen mode

NestJs artillery - Insert 1 million records test

πŸ”— Check out the full source code and benchmarks on my GitHub:

PHP/Swoole: https://github.com/roman-shneer/high-load-event-processor-php

NestJS: https://github.com/roman-shneer/high-load-event-processor

Top comments (0)