The Rise of Hybrid PHP: Blending PHP with Go and Rust
Original - 2025-08-30 - yeknava - 2 minute read
We used to develop our application as a single DDD monolith (let’s call it the mother) with several smaller microservices around it (the children) to gain some specific advantages. Most of these microservices were built in Go, while the core monolithic service was developed in PHP 8.3.
This stack served us well for a long time. The Go microservices efficiently handled our high-throughput requests, and the carefully designed monolith allowed our relatively small backend team to deliver features quickly and with confidence. It was a good balance: speed where we needed it most, and stability and productivity everywhere else.
As many of you may have experienced, 80% of your traffic often targets only 20% of your APIs—the well-known Pareto principle. And unsurprisingly, those hot 20% endpoints are usually the ones where performance matters the most. In the past, our strategies included writing highly optimized code, adding extreme caching layers, or extracting certain parts into Go-based microservices. While effective, these approaches added complexity and operational overhead.
But now, thanks to new capabilities in the PHP ecosystem and the rise of powerful libraries and runtimes, it’s becoming much easier to keep more logic inside the monolith while still achieving excellent performance. Let’s look at a few exciting options:
1. FFI (Foreign Function Interface)
PHP’s FFI feature allows you to call C code directly from PHP. This opens the door to system-level operations or performance-critical logic without leaving your PHP project. Of course, you need to be mindful of context switching costs, but for the right use cases, it’s a game-changer.
2. Rust-Based Extensions
If writing raw C isn’t your cup of tea, you can now write PHP extensions in Rust (or even Zig). This lets you offload heavy, performance-sensitive parts of your application to safe, memory-efficient, compiled code. Rust, in particular, offers memory safety guarantees without sacrificing speed, which makes it a great fit for extensions that need to be both reliable and fast.
3. Go-Based Extensions with FrankenPHP
We’ve recently switched to FrankenPHP (after seeing it become officially supported by the PHP Foundation). Running PHP in FrankenPHP’s worker mode is impressively fast—sometimes over 4x faster in our benchmarks compared to traditional setups.
Even more exciting, a recent release introduced the ability to write PHP extensions in Go. This feature is something we are actively exploring because it would let us build high-performance APIs in Go and expose them seamlessly inside our PHP monolith. That way, we can combine the productivity of PHP with the raw speed of Go, without needing to split everything into separate services.
But Why Not Just Rewrite Everything in Go or Rust?
It’s a fair question—and one we’ve asked ourselves too. There are two main reasons why we don’t simply migrate the entire backend:
1. Rewriting is costly. Many applications are already large and stable. Rewrites are risky, time-consuming, and often introduce more problems than they solve. In most scenarios, a rewrite should be the very last option.
2. PHP is still a great fit. For the majority of the application, PHP does the job well. It’s fast enough, developer-friendly, and supported by a large ecosystem. For those few cases where you truly need maximum performance, you can now selectively write parts in Go or Rust as extensions—rather than rewriting the entire system.
In short, the modern PHP ecosystem gives us the best of both worlds: the ability to build quickly and confidently in PHP, while still having powerful options (C, Rust, Go) for performance-critical parts. This hybrid approach lets us stay productive without sacrificing speed where it matters most.