Objective
In recent times, there’s been a noticeable industry shift toward Node.js for developing REST APIs, even though mature languages like Java, Python, and PHP already exist. This motivated me to evaluate Node.js performance against PHP, which is less commonly used in the industry today — even though many CMS platforms and web applications still rely on it.
Before choosing the right server-side scripting technology, I wanted to check how efficiently each one handles HTTP requests.
So, I decided to measure their real-world performance under load.
The goal was to find how Traditional PHP (with Apache), Modern Laravel Octane, and Node.js (with NestJS) behave under concurrent traffic.
But before diving into the results, let’s first understand how each of them processes requests.
PHP (with Apache HTTP Server)
Traditional PHP runs in a request-per-process model.
Each HTTP request spawns a new PHP process or thread under Apache’s mod_php module.
After execution, the process ends — meaning the entire runtime and application state are re-initialized for every request
Laravel Octane (with RoadRunner)
Laravel Octane introduces a persistent application server that keeps the Laravel app in memory between requests.
It uses *RoadRunner *(or Swoole) as the server, drastically reducing startup cost per request.
Node.js (NestJS Framework)
Node.js uses an event-driven, non-blocking I/O model.
It runs on a single thread but uses an event loop to handle thousands of concurrent connections efficiently without creating a new process per request.
Test Setup
API Endpoint: Get User Data(10 records)
Concurrent Users: 50 (VUs)
Duration: 10 seconds
Load Test Tool: k6 (Grafana)
Test Results
| Framework / Stack | Requests Count | Mean Duration (ms) | P95 (ms) | P99 (ms) | Mean RPS | Max RPS |
|---|---|---|---|---|---|---|
| PHP + Apache | 107 | 6096.39 | 15197.79 | 15548.40 | 6.68 | 8.0 |
| Laravel Octane (RoadRunner) | 2311 | 217.91 | 288.76 | 729.08 | 231.1 | 247.67 |
| NestJS (Node.js) | 5237 | 95.67 | 130.04 | 402.85 | 585.33 | 247.67 |
But with the above performance results in mind, should we choose Node.js for our next project?
No — not just based on that.
Let’s examine the nature of PHP and Node.js before making a decision.
Node.js, can handle a large number of concurrent requests efficiently because, when your code makes asynchronous I/O calls (such as database queries, file reads, or HTTP requests), Node.js delegates these operations to the background thread pool.
While those tasks are running in the background, the event loop continues processing new incoming requests — which makes Node.js highly performant for I/O-bound workloads.
PHP, on the other hand, works differently.
Each worker can serve only one request at a time.
A worker executes your PHP script from start to finish and remains blocked until all I/O operations (database, file, or HTTP) are completed.
This means concurrency in PHP depends on how many workers are configured
But what happens when the code involves heavy or complex logic?
Now, let’s consider what happens when your application contains heavy computation or complex logic — this is the crucial part when choosing the right technology.
Node.js:
If one request performs a CPU-heavy task (for example, complex calculations, image resizing, large loops, or encryption), the event loop becomes blocked.
During that time, other requests cannot be processed, which can slow down overall performance.
PHP:
Suppose you configure 4 workers — this allows 4 requests to be handled simultaneously.
If one worker is busy with a heavy task, the other 3 can still continue processing other requests.
Because each worker runs in its own isolated process, one slow request does not affect others.
Conclusion
I hope this explanation helps you understand the fundamental differences and guides you in choosing the right scripting language for your next project.
Top comments (1)
The fact that you didn't share the server configurations or code means nobody can reproduce your test.
While node is the better choice for high concurrency, I rather use a more general purpose language like Go to create API's that need that kind of capacity.