Last time I posted a similar titled post, it was 15 years ago and about a benchmark comparison on four PHP frameworks out of which one is no more, one is pretty much alive only in name and one is struggling against its status of irrelevance. In short, only one of those four PHP frameworks is still up, alive and kicking.
15 years is a very long time in tech, it’s an age. Back then PHP framework being able to handle 45 requests/second was being considered good. A lot has changed since then, both on PHP level and framework level.
The Present
PHP has improved a lot over the years; v7 brought with it a big jump in performance, v8 now improves on it even more. Then last year a sneak peak was shown of Laravel Octane as to how Octane super-charged Laravel API was able to handle several thousand requests per second. All examples I’ve seen so far for Octane speed tests etc. have shown similar results. All of this makes Laravel Octane very promising given how many requests per second it can handle. But that was not a true measure of Octane’s performance, we’ll come to that in a bit.
Here & Now
But if I’m looking at creating a high performance API today, I wouldn’t look only at PHP. There’s a bunch of new tech stacks that have come in last 15 years and some of them knock it out of the park when it comes to performance; Node.js & Go are two of these tech stacks.
Now coming back to Laravel Octane’s performance measurement. Of all the benchmarks I’ve seen so far, they all either measure with default Laravel homepage (which is static content) or a “Hello World” response which again is static content. However, in a real world API or app, one would hardly use static content and is likely to use a data source to fetch data based on certain query parameters. So it’s only fair that while evaluating which tech stack is more performant, some data source is used so as to try and simulate a real world situation.
Testing a simulated real world scenario
Here is what the test environment had:
- Freshly provisioned Ubuntu Server 20 LTS
- PHP v8.0 + Swoole + Laravel + Laravel Octane
- Node.js v16.x LTS + Fastify
- Go v1.17.x + Fiber
- MariaDB
I wrote a basic API in Laravel, Fastify & Go Fiber which would connect to a database in MariaDB and get 10 records from a posts
table sorted in descending order by date after skipping first 5 records. It was a simple SELECT
query (see below) without any joins or groupings etc.
SELECT id, author, title, content, created_at FROM posts WHERE status='publish' ORDER BY created_at DESC LIMIT 5, 10
No caching was implemented so as to measure the actual performance of each stack. But to keep things close to real, appropriate indexes were created on the table to prevent MariaDB from taking a million years to run this query. 😉
I ran four tests, and to say that I was surprised by the results would be an understatement. :/
Laravel Octane with normal route
This was just a regular request handled by a normal Laravel route. Only thing special in this case is that instead of being served by PHP-FPM & Nginx, this is running on Laravel Octane served by PHP’s Swoole extension. This handled ~138 requests per second.
Laravel Octane with Octane route
Laravel Octane comes with the feature of specifying an Octane route which provides a NOS boost to an already super-charged app. The downside of this is that it bypasses (almost) all middlewares (from what I understand) and might not lend itself well to all usecases. But since it can work in my usecase, I gave it a shot. This handled ~383 requests per second.
Node.js + Fastify
Fastify is a fast and low overhead framework built on top of Node.js. It’s lightweight and has low footprint just like Express.js but unlike the latter it provides a bit better development experience. This handled ~2022 requests per second.
Go + Fiber
Fiber is a web framework for Go built on top of Fasthttp (a very fast HTTP engine written in Go) keeping ease of development and app performance in mind. This handled 4361 requests per second. 😮
The Revelation!
All the performance benchmarks of Laravel Octane I’ve seen showed it besting Node.js. In this test since a traditional RDBMS was involved as a data source, I knew the results would be different but I was still hoping it would be a close one between Laravel Octane and Node.js. However, Fastify just blew Laravel Octane out of the water; 383 requests/second vs 2022 requests/second – there is just no comparison. And let’s not even talk about 4361 requests/second metric from Go Fiber – that is in another league altogether. The Fasthttp engine truly lives up to its name and then some.
I know there the performance in the Laravel Octane test-case could’ve been boosted even more with use of Swoole Tables but that would’ve been an unfair test by implementing caching only on one stack. Depending on the use-case of the API, a cache/CDN can be put in front of the API allowing it to handle way more requests per second and deal with any connection concurrency issues. At that point, what stack is used becomes moot.
I’ve not written away Laravel Octane. It’s a very interesting stack and I would be exploring it further.
Takeaway
Go Fiber is clearly way ahead of other stacks as far as performance and concurrency are concerned. Why isn’t everyone building their APIs and apps in Go Fiber then? Because not everyone and everything needs extreme performance. It isn’t that nobody is building in Go Fiber but the fact of matter is that it isn’t for everyone.
Go Fiber isn’t void of challenges. It’s documentation is sparse & community around it is small – when compared to other stacks. From an engineering leadership perspective, one big concern I’d have would be the short supply of Go developers in the market. Building critical APIs on a stack and not having enough people to improve/maintain it does not sound like a good idea. Personally, I find Go’s syntax a bit weird and complicated. I haven’t worked with C in over 17 years, Go’s syntax reminds me of it, and I was never a fan of writing C code.
From a practical point of view, Node.js + Fastify look more appealing and even PHP + Laravel Octane are not out of question either. Both PHP & Node.js have great documentation & communities around them. More importantly, it’s comparatively easier to find developers for both PHP & Node.js.
But most importantly, the choice of what to use would be subjective and depend on the stack(s) a business is invested in. Unless there is a very specific use-case which warrants the use of a specific stack (like Go Fiber), a business is likely to use a stack they are already heavily invested in to try and avoid the chaos which follows with stack fragmentation unless the software engineering vertical of the said business is a behemoth which eats tech stacks for breakfast.