The Greatist Multi-Tenant Architecture
It’s a story…
Healthline has experienced major growth over the past couple of years. This growth has come as we’ve worked to reach more people by adding websites to our Healthline family. Last year we brought aboard Greatist.com, a health and wellness website.
Our union with Greatist meant critical decisions about their technology stack needed to be made. Should we keep running their Drupal instance or migrate them to our WordPress? We chose to migrate knowing that meant recreating their site too. You’re thinking that isn’t hard, right? Create a new WordPress theme and ta-da all finished. But running a headless WordPress setup puts the kibosh on making themes. So why not create a copy of the Healthline website and change the design. No big deal.
At this point, a warning alarm in your developer’s brain should go off. Don’t know why? Any seasoned developer knows duplicating code is a general no-no. In true nerd fashion, we have acronyms to help us remember, DRY (Don’t Repeat Yourself) and DIE (Duplication is Evil). We avoid code duplication through abstraction. Too much abstraction leads to unnecessary complexity and maintenance nightmares. Think of making changes to code with too much abstraction as the same as playing with fire. You’ll likely end up starting a forest fire of broken code. Setting up a multi-tenant architecture felt like a balanced solution for both concerns.
There’s always a catch!
Before I explain multi-tenant architecture, let me give you a heads up. A multi-tenant architecture implementation takes lots of time and effort. You need some detailed planning and design. Throw in infrastructure setup and code refactoring and you have a hefty project.
I have yet to meet an executive that likes to hear about a solution that will take lots of time and effort. Time is money!
As you read on, you’ll pick up some selling points to sweeten the pot.
Fortunately for us, the development of a multi-tenant architecture was underway. We started working on migrating MedicalNewsToday.com (MNT) in January of last year. We placed the MNT migration on the back burner and finished the solution with Greatist.
A multi-tenant architecture is where many tenants use the same resources. In our case, the Greatist, Healthline, and Medical News Today properties are tenants.
There are a few types of multi-tenant architectures. They vary in the amount of control given to the consumer.
- Infrastructure as a Service - DigitalOcean, Linode, Rackspace, Amazon Web Services (AWS), Cisco Metapod, Microsoft Azure, Google Compute Engine (GCE
- Platform as a Service - AWS Elastic Beanstalk, Windows Azure, Heroku, Force.com, Google App Engine, Apache Stratos, OpenShift
- Software as a Service - Google Apps, Dropbox, Salesforce, Cisco WebEx, Concur, GoToMeeting
All About the Cost
The whole point of multi-tenant architecture is to lower costs. The above services are more affordable because you share the costs with others. For instance, think of the cost you’d incur running Salesforce in-house. You’d need to pay for:
- Utilities (power & server room with air conditioning)
- Data backup system
- Data redundancy system (in case of downtime)
- System Administrator salary
Return on Investment
Despite the significant setup cost the future savings were persuasive. Having Healthline, Greatist, and MNT share code and infrastructure would result in:
- Less code and architecture to maintain, set up, update and upgrade
- Less time required to add new tenants
- Less third-party services to pay
Decreases in those areas result in decreasing the number of employees you need. I daresay employee pay and benefits are among the top three largest expenses for most companies.
The Implementation Lowdown
By now you want to know how we implemented and setup our multi-tenant architecture. Here are some high-level diagrams and explanations.
- A user requests an article from healthline.com.
- One web server within the cluster assigned to Healthline traffic handles the request. Each tenant has a web server cluster assigned to handle their requests.
- That web server has an environment variable set to identify it as part of the Healthline cluster. Each web server in the cluster has an environment variable set to identify the tenant.
- The web server runs its copy of the deployed frontend code.
- Based on the environment variable, code reads Healthline’s configuration file. Each tenant has a configuration file. The file defines the location of the APIs and feeds for that tenant.
- Code requests article from API providing Healthline data.
- Based on that environment variable, code applies the Healthline theme. Each tenant has a theme defining the colors, fonts, and other CSS properties.
- The web server provides the user the article with Healthline styling and colors.
- Frontend code requests a Healthline article from the article API.
- One web server within the API’s cluster handles the request.
- The request calls the endpoint designated to return Healthline articles. Each tenant has an API endpoint of their own.
- The web server reads the article from the Healthline folder located on cloud storage. Each tenant has a folder storing its articles.
- API does transformations to return a consistent response no matter its originating CMS.
There is no “I” in “Team”
The diagrams make it appear easy. In actuality, it was a big milestone for engineering.
- Added and changed code to apply theme based on the requested website
- Added and changed code to access the APIs and feeds based on the requested website
- Deploy code to each cluster of Docker containers
- Added and changed code to run unit, integration, and visual tests for each tenant
Content Management System (CMS) Team
- Save draft and published articles to tenant’s folder on cloud storage
- Provide feed data for each tenant
- Setup and assign clusters of Docker containers per domain