Monoliths, Services and PHP

Share on X (Opens a new window) Share on Tumblr (Opens a new window) Share on LinkedIn (Opens a new window)

Lately, I’ve been diving deeper into microservices architecture. While exploring examples of where they shine and where they fall short, I couldn't help but reflect on how PHP approaches some of these challenges in its own unique way. In the end, the right answer still is "it depends" – but I'm leaving my notes here in case it helps anyone with building their next app.

The monolith

This is where it all began. All your code, in one place. The thing is, if you look under the hood, assuming you've done a stellar job organizing and modularizing your app, it’s not far removed from the structure of a microservice architecture.. Take this basic diagram for example:

What we have here is the backend for a very simple file sharing web application. The monolith handles all requests, and if we dive a little bit deeper, we'll see they all go through the router, followed by a number of middleware components that take care of authentication, rate limiting, and eventually the controller for the route. From there, depending on what it is that we're doing, we'll make the call to the necessary part of our service layer. This is where the vast majority of our business logic is located, as well as where we make the calls to any other internal or external services, or the persistence layer.

There's some important implicit contracts in that graphic. It assumes that each "service" is fully responsible for maintaining its data tables in the persistence layer, and you always need to go through that service to write or read it. It's a significant assumption, speaking from experience. It'd be difficult to maintain such clear boundaries long term if it's all part of the same codebase, because as software evolves, it's tempting to take shortcuts in order to ship features faster. As the people working on a system change, it's possible some of the reasoning behind it gets lost too. Anyway...

Assuming the above holds true, the only difference between the monolith above and a service oriented app below, is that we've moved all the components from a single codebase to the infrastructure level. The core principles of good architecture don't change, whether you're writing a monolith or a microservice.

That's not to say there aren't tradeoffs between one and the other. Let's explore that too.

Breaking it up

The strength of the monolith lies in simplicity. One language, one framework, one stack. It's relatively simple to set up and deploy, locally and in production. So why go through the trouble and complexity of maintaining the infrastructure for a microservice powered backend?

  • Ability to scale individual services independently.
  • Technology limitations. Whether it's for performance reasons or library support, microservices allow you to always choose the right stack for the job.
  • Failure resilience. When one service goes down due to a bug, the rest of your system can keep functioning.
  • Security. If you have any potentially vulnerable dependencies – say for processing user uploaded files – the flexibility of deploying exactly what you need only where you need it helps isolate those from the rest of the system.

While microservices are on the extreme, chances are if you're building something other than a simple business website, a WordPress site, or anything beyond a basic CRUD application, you're likely already in a service oriented architecture. And the monolith just serves as the largest piece of that.

The benefits become really obvious once you add asynchronous processing to the mix. You wouldn't want your client-facing web servers to be slowed down by some massive background tasks like transcoding video files, or running large data aggregation queries. Having a dedicated app and infrastructure for those tasks is the only thing that makes sense.

PHP: Blurring the lines

It's 2025 already and contrary to many popular predictions, PHP is still not dead. In fact, it's thriving. But it's not the first language that comes to mind when implementing microservices. You could even argue it doesn't make the list at all. Why? I think at least part of that is because it solves some of these problems in a very unique way.

Unlike any other popular language on the web, the way it's usually deployed with Apache or FPM, PHP is stateless. Requests are completely isolated from one another, and resources are freed as soon as they complete. This makes horizontal scaling extremely easy – there's no spin up or cold start penalty. Just upload the files and you're done. This is what originally allowed Facebook to scale as quickly as it did, though they've since moved on.

The code is lazy-loaded based on the current execution path. This characteristic means that even if we introduce a fatal error, it'll only affect the part of the application where it's called directly. All other routes or jobs would keep running as expected.

With these two, it goes a long way to solving points 1. and 3. from the list above, except for cases requiring the most rigorous fault tolerance, or where PHP execution times themselves become the bottleneck. But it's not without downsides either:

The language and most of its ecosystem were built around HTTP. And even though we're seeing progress, I personally still wouldn't consider it a true general purpose programming language.

  • Because of the assumption that the process is killed once the request is fulfilled, memory usage or cleanup is not a concern anywhere in the ecosystem. For long-running processes, this results in memory leaks.
  • Without resorting to exotic extensions or libraries, PHP should be considered single-threaded and fully synchronous. While there are ways around it, the code is very clunky and often just a suboptimal solution. For any real-time communication requirements, you'll have to turn to something else.
  • Linked to the above, if you're relying on anything other than HTTP for communication between services, PHP is not the tool.

In a microservice architecture, this could be considered very serious blockers. That said, because of the characteristics mentioned earlier, as long as adding more servers is your biggest problem, I'd argue PHP potentially allows you to take your monolith much further than any other technology.

So, what should I use for my next app?

As much as I hate to admit it, the answer still very much remains "it depends". And could even be neither. Especially in the last few years we've seen an emergence of quite a few backend as a service solutions like Firebase or Supabase. They already accomplish a lot, and for everything else, there probably is a dedicated cloud service. I think now more than ever, it's pretty realistic to get to an MVP and start validating your product while hardly writing any backend code.

Of course, once the product is validated, as your needs and customer base grows, you might opt to transition some of these services to in-house solutions to manage costs better. At which point the things I mentioned in this article will become relevant. Until then, keep calm and focus on getting your customers.

X Click to share (Opens a new window) Tumblr Click to share (Opens a new window) LinkedIn Click to share (Opens a new window)
Published with Ghost