As WordPress has matured, more people are using it as an application platform. As we move towards Matt Mullenweg’s vision of WordPress as the open source OS of the web I think it’s important to question some of our conceptions of the way we tend to use WordPress.
Traditionally a WordPress site is executed as a single monolithic unit. This is counter to a growing trend in web development towards microservices — many small single-purpose applications configured to act as one unit.
For example, consider static HTML caching. If you are following the monolithic approach you would add a plugin that generated and served the cache inside of WordPress. Or you might configure Varnish or nGinx on your server to serve cached HTML. On the other hand, when using the microservice approach, you would use a separate server or network of servers to implement the cache, delivered with a CDN.
For the web app I develop, Caldera Forms Pro, we are moving towards a microservice approach. While the app was originally one central Laravel app that used our WordPress site for eCommerce, the last feature we implemented — improved error logging — was implemented as a separate microservice built in the microframework Lumen.
Embracing the microservice architecture was the subject of my WordCamp Montreal talk — Our Hybrid Future: WordPress As Part Of The Stac. In this article, I will discuss what the microservice architecture is and how to use it to improve your WordPress application development.
The Monolithic Architecture Pattern
A monolithic application built as a single unit. The server-side application will handle HTTP requests, execute domain logic, retrieve and update data from the database, and select and populate HTML views to be sent to the browser. Martin Fowler
Understanding the microservice pattern is easier if we first define its opposite — the monolithic architecture. A web-app is considered monolithic if it is created and executed as one single entity.
The traditional WordPress architecture conforms to this in a lot of ways. You have one server — dedicated, VPS or part of a shared server — that runs PHP, MySQL and a webserver — apache, nGinx, etc — that runs the whole program. We add functionality to that program by installing other programs to that server — Redis, Varnish, etc. — and adding more code to WordPress — IE plugins.
The key benefit of monolithic architecture is simplicity. You have one program, one server and one set of technologies.
The Microservice Approach
The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.” Martin Fowler
As opposed to one do it all program, the microservice approach to web application design says that each unit of the application should be its own program running on its own server or server network.
The key benefits are increased encapsulation. This encapsulation aids in scaling challenges. Because each part of the program is running on its own servers, each server network can be independently optimized and scaled according to its own needs.
Increased encapsulation has many benefits beyond scaling. By making each part of the program a separate code base, they can be developed and deployed with independent schedules.
Also, since these services are free-standing and independent by design, they can be reused in other applications. Amazon.com is an example of a large-scale web-app built using a microservice architecture. They built each part of the application as a separate service, and turned many of them into free-standing products available through Amazon Web Services. If Amazon had somehow achieved their scale without using microservices, they wouldn’t be able to sell us their file storage solution — s3 — or email solution — SES.
Microservices can also lead to cost savings. Using MailChimp to handle an important function of a site — email marketing — is way cheaper than building your own email marketing service for every site.
WordPress Isn’t Totally Monolithic
WordPress.com was the first large scale WordPress site — one multisite install with millions of users. Of course it’s way more complicated than that. If Automattic had not developed and implemented tools to distribute that processing and use microservices their technology literally would not have worked.
The first step towards the microservice architecture is distributing processing across networks. HyperDB was developed at Automattic to allow for a redundant network of MySQL servers to be deployed to distribute the database of a WordPress site. HyperDB and similar systems are ubiquitous today in WordPress.
We also use CDNs to offload serving static files. We use 3rd-party payment gateways to handle payments and manage subscriptions. We use transactional email providers to send emails.
Quality WordPress hosting isn’t really about the server anymore. It’s about the network of services that are used to scale a site and provide consistent performance globally.
Human Made, an enterprise WordPress Development Agency, has a great guide to scaling WordPress. Their list of plugins for scaling WordPress are almost all for distributing the processing of WordPress across specialized services.
Why Microservices Are Important To WordPress Developers
Normally when we think about microservice we talk about scaling servers. I’m not a devops person. So, I’m not going to discuss distributing or containerizing your server stack. I get why you should, and there are plenty of other resources out there on that.
On the other hand, I do build WordPress plugins as well as web applications. Thinking in terms of microservices has helped me rethink how I approach these problems. That’s what I want to discuss.
Every engineering decision we make is a compromise that has downsides. We can’t avoid this. But, microservices reduce the scope of compromises. Since each microservice is its own independent program with minimal responsibilities, the technologies chosen and their implementation only has to take into account one small subset of the larger programs requirements.
From the perspective of WordPress developers, we can look at microservices as a way to get around the limitations of WordPress. Having one monolithic site that advertises a product, sells that product and handles subscriptions for that product is a major scaling problem. If that product is an app and that app is built in WordPress, it’s now even more of a challenge.
But what if we rethought that as four or more WordPress sites connected by the WordPress REST API? For example, what if you moved the subscription management to a separate site? Then you would not worry that a large batch of renewals were being processed at the same time that you had a lot of potential customers on the site. The effect of subscription renewals would renewals processing being delayed slightly, not your site’s front-end loading really slowly.
This is even more important if you are building an app with WordPress as the backend and are using WordPress to sell, market and support that app. In this scenario, increased site traffic would degrade app performance and vice versa. Optimizing a WordPress site for serving static content is very different from optimizing one for being the data provider of an app.
Separating the two into separate sites allows you to optimize and allocate resources to each one independently. Also, it means that you can develop each one independently.
An even simple example of this would be a site where each post type had its own private subsite that served the content into the main site via the WordPress REST API.
WordPress As Part Of The Stack?
Once you start thinking in terms of how to split WordPress into multiple WordPresses as I suggested in the last section, it is natural to start asking why all of those services have to be built in WordPress. The answer is they don’t.
I love WordPress, but I don’t think it’s the right tool for every job. A web application I develop Caldera Forms Pro uses WordPress for many parts of the stack, but not the whole thing. WordPress handles eCommerce, marketing automation, documentation and more. But the main app is built in Laravel. As a result, usage of the app has no effect on our main WordPress site.
Essentially we turned our WordPress site into a microservice, that bridges to many other services — Stripe, PayPal, Convertkit, etc. While our main app is still fairly monolithic, I recently pulled the distributed error logging system out of the main app and into a microservice powered by Lumen.
I intend to develop new features for this app as microservices with the main app as the authentication provider and minimal centralized management that is needed to make microservice architecture work.
Always Communicate Via HTTP APIs
When working with microservices, you have to solve the problem of how to get one service to trigger a process on another service. Early on when working on Caldera Forms Pro I considered using Laravel to run WP-CLI commands on the WordPress site. This would have worked in my local development environment where both apps were running in the same VM at the time.
If I had decided to communicate between the apps via their CLIs, then I would not have been able to deploy them to separate servers, which is what we did and was always the plan. This one shortcut would have removed a major benefit of the separating functionality into different services.
Instead, the different services always communicate via REST APIs. I used the WordPress REST API to add endpoints to our WordPress site. The Laravel and Lumen apps are essentially headless CMSs — they are datastores accessible via REST APIs. The main app has only one view, which serves a VueJS single page web app.
Feature Complete Services
One cool thing about building with microservices is that each service has very few responsibilities. This enforces a practical minimalism of scope. If a service does one thing and does one thing well, you can leave it be.
Yes, your business may develop new needs. When that’s called for, create a new service.
As WordPress developers, we’ve been trained to separate functionality into plugins so that they can be developed independently and reused. Microservices take that approach one step further. We can solve repetitive problems across multiple projects with the same microservice or instances of that microservice.
The microservice approach maximizes the potential for reuse of code. Rember Amazon.com isn’t just a leader in eCommerce, many of their competitors are paying them to use the services that were necessary to make Amazon.com. Microservices can more easily become standalone products than other types of code you develop for a specific project, which is neat.
When we begin studying code, you learn a few things. Encapsulating functionality around a single responsibility is good design. We learn that writing code for reuse is good design. Embracing the microservice approach applies these important maxims to the architecture of our program. And it enforces limits on the scope that aid in applying both of these maxims to our code in a way that has enormous practical benefits.
By making each part of our program independent, we can choose technologies and solutions more granularly.