The Dubai client who wanted us to rewrite in Node 'because PHP is old'
Contents
Story time, because this happened again this month and I want to have a link to send next time.
Logistics client in Dubai. Laravel app we built in 2021, about 40k shipments a month, drivers, tracking page, invoices. They hired a new CTO from a big company. First meeting: "PHP is old, we need to rewrite in Node, NestJS, microservices. How long?"
I did not argue. I said: give me two days to profile, and I will give you two numbers. One for the rewrite, one for whatever the profiler finds. Then you choose.
What two days of profiling found
- p95 on the API was 820ms.
- The tracking page had an N+1 on shipment events, about 60 queries per page view.
- The invoice report did a full scan on a 9 million row table. No index on
(client_id, created_at). - Sessions were stored in files on an NFS mount. Yes. NFS.
- OPcache was enabled but with
validate_timestamps=1and a tiny memory setting, so it was checking every file on every request, on the same NFS.
What we changed
; php.ini (production)
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
With validate_timestamps=0 you must reload PHP-FPM on every deploy, otherwise the old code stays cached. We added it to the deploy script. Then: eager loading on the tracking page, one composite index, sessions moved to Redis.
p95 went from 820ms to 140ms. Three days of work including testing.
The two numbers
Rewrite in Node: 5 months, 3 developers, AED 180,000, and the usual risk that you rebuild the same app with new bugs. Profiling fix: 3 days, already done, here is the graph.
The CTO is not stupid. He looked at the graph for a long time and said "ok". We did agree on one thing he wanted: the live driver tracking with websockets is now a separate service. We used Laravel Reverb for it, but honestly Node would also have been a fine choice there. Use the tool where it fits. Rewriting a working business app because of the logo on the language is not engineering, it is fashion.
Lesson I keep learning: never argue language with a client. Argue with a profiler and two numbers. The profiler wins every time 😊
Get the best of #php_still_pays weekly
One email each Monday with the most useful posts. No spam; unsubscribe in one click.
Comments
Sign in to join the conversation.
Sign in to comment