Here at Futurice, we’ve had some experience with content management systems like Liferay and Drupal. Many traditional CMSes are large monolithic packages, which can cause problems. We’ve had our share. The most essential drawback to using a full CMS is probably the tight coupling between content creation and content presentation. We’ve also had issues with scalability, performance and build times, among others.
Last year a customer asked us to build a public, CMS-powered website. The customer provided us with strict performance, scalability and availability requirement, which drove us to think of an alternative approach to the conventional CMS-solution. We wanted to make a modern, horizontally scalable website, but this seemed difficult to do with a traditional CMS-architecture. We also knew that there were going to be integrations to customer’s backend services at a later date. Implementing these on top of a CMS sounded like a huge mess. To address these issues, we started to consider separating content management and presentation as dedicated services, which would then communicate via a well-defined API. Completely separating the CMS from the presentation seemed to bring with it some extra benefits like enhanced security, too.
Initially, we considered using a content management platform, such as prismic.io or Contentful, and building a separate presentation layer with a web framework. This seemed like a good solution at first, but there were two problems. First, the customization demanded by the client’s requirements seemed too complex to handle with a service where making alteration on the code level wasn’t possible. Second, the customer thought they might need an integration to an existing SSO-service for logging in to content management. This seemed problematic to do with a solution we weren’t hosting ourselves.
With SaaS content management services ruled out, we considered using just the content management features of a traditional CMS system and creating a custom API for communication with the separate presentation layer. We decided on Drupal for the content management layer and Symfony MVC framework for the presentation layer. Although we would have preferred using something other than PHP, we felt that there were some benefits to be gained from using the same language in both layers.
As with many projects at Futurice, we decided to use Amazon AWS for hosting. Since only the customer’s content managers use the Drupal, a single server instance with a replicated database seemed to suffice. The public website requirements dictated small response times and high availability, so multiple Symfony instances behind a load balancer were needed. We also set up automatic scaling, so that new instances would be added dynamically when the load gets high. High availability requirements meant that we couldn’t have frontend instances be directly dependent of Drupal. We solved this issue by implementing Redis caching between the presentation and content management layers. Currently, the cache is being populated periodically, but with some extra effort it could be done by hooking into Drupal post save process and pushing the data to cache when updating content in CMS.
A simplified architecture diagram for the solution
Most of the work involved was quite straightforward. The integration between Symfony and Drupal was implemented using a custom JSON API module to Drupal. Most of the work done in the presentation layer was just normal frontend coding.
There were some problems with the architecture, though. Content preview before publishing was probably the biggest issue. Since Drupal normally utilizes it’s own presentation layer for displaying content in the administration view and our solution had a separate presentation layer, we had to build a custom solution. We also had minor problems with a couple of situations where third-party Drupal modules required direct access from presentation layer to Drupal, but they easily resolved.
Was it worth it? I think it was. The overall architecture of the service is clean, with high availability and good performance. Since we are now starting to integrate the client’s backend services to the presentation layer, we’re going to implement the involved business logic in a separate service as well. This allows us to maintain a clean separation of concerns and responsibilities while adding new features.
All this will get us closer to a microservice architecture, which seems like a good solution for services like this.
We will soon publish another blog post on our experiences with prismic.io in another CMS project. See the posting here.