Effective DevOps Practices for Enterprise Websites
We articulate some devops best practices around managing and upgrading an enterprise website on an ongoing basis. We are focused more on what it takes to add new features rather than aspects such as managing performance, security or uptime. Also, for purposes of simplicity, we will illustrate these concepts on a WordPress setup that runs on the WPEngine hosting platform. You will find that these can be extrapolated quite naturally to other CMS and hosting environments as well.
What not to do
If you are running an “enterprise” website, then there are a few things which you shouldn’t be doing as they make the site fragile and error-prone.
- Have only a single production instance setup (with no supporting stage or development environments)
- Push code to production or stage environments through sftp or ftp. If you do this, you essentially have no rollback capabilities. You should set up your environments to have version management baked into them (such as git for example)
It’s quite plausible that your site is simple enough that it doesn’t warrant some of the complexity mentioned above. In that case, this post might not be too relevant to you.
The Typical Setup
A typical enterprise website setup includes three environments: Production, Staging and Development.
The production website is the site that is seen by the end users. It is setup on a high-performance infrastructure, involves CDNs for large traffic volumes and is locked down from a security perspective. Marketing teams generally push content directly there (such as news, blogs, updates and such) after the content goes through some internal publishing and approval workflows.
The staging website is kept closely in sync with the production environment, and is used to review new functionality and content before it is pushed into production. Typically this environment is also used by the development team to push quick fixes, bug fixes and minor enhancements. The frequency of operations tends to be hours/days here.
The development environment is typically used for long-term development and large new functionalities that need extensive development and testing resources, before they are evaluated by the marketing teams for approvals. The timescale of operations here tends to be in the range of weeks.
When you create these three environments in a WPEngine setup, they will look like below. Each environment can also be granularly managed based on several options provided.
Code vs. Content
Code and Content are two very distinct areas that need to be managed in your devops processes across the dev, stage and production environments. They both require very different approaches and workflows.
In a WordPress setting, code refers to all the PHP, CSS, JS and HTML files that comprise the WordPress CMS core and also the plugins that you have installed. Content refers to the data in the database as well as the assets in your media library.
A key principle to remember in general is that code typically moves from dev -> stage -> production and content moves in the reverse. We will explain this process in more detail in the next sections.
Best Practices for Code Management
As we mentioned at the outset, the starting point for a robust code management is to ensure that you are using git instead of merely pushing files to the environments via sftp or ssh. Git lets multiple developers work on their local repositories and merge regularly into a central repository.
This is an effective strategy and usually suffices when you are working with a single remote repository. However, if you need to straddle multiple environments — each with their own git repositories — this won’t be adequate. The reason is that you cannot manage codebases across multiple independent git repos.
To address this situation, you need to do use an external code management system such as Bitbucket, Beanstalk and others. They work as shown below:
You create a central repository and branches as needed. For eg. you might have a development branch that deploys to the development git environment. After doing testing here, you can merge the dev branch code into main. This then gets pushed to the staging environment. After any additional code changes this gets deployed into production. So, you have a central repository that tracks commits and versions across multiple environments.
A sample implementation in Bitbucket is shown below:
Best Practices for Content Management
Content Management is quite a tricky problem because most CMS platforms store content in a database. Although media is stored in folders, the pages, templates etc are stored in a database. This means there is no easy way to do “version management” because of the fundamental limitations of databases in this regard.
As mentioned earlier, content typically tends to flow from production -> stage -> development environments.
The reality is much more complex in fact — as shown in the image below:
- At any point in time, the marketing teams will be adding content (news, blog posts etc.) directly into the production environment and publishing it live.
- Simultaneously, the support teams will be making fixes and minor enhancements that will require both code and content changes to be done. These changes after review by the marketing teams will need to pushed to production.
- Finally, the development teams will be making long-term enhancements and large functionality changes in the development environment. Naturally, this will involved code and content changes, that will eventually need to find its way through stage and into production.
It is quite a tricky affair to keep the content in sync across all these environments, with all these activities happening simultaneously.
Guidelines for Effective Content Synchronization
At a baseline level, you need to have regular backups of all environments. If you use platforms like WPEngine, they do this automatically for you:
The next step is to ensure that you keep production content very closely in sync with stage. Stage has to be a true replica of your production and shouldn’t be more than a week or so behind production.
Platforms such as WPEngine let you do this by copying production en-masse into stage. (Note that this copies over both content and code.) You can also use products such as WP Synchro to automatically schedule DB backups and migrations. They give you a lot of granular control over what to backup and when.
The final set of content scenarios that need to be addressed involve pushing “net new” content from development or stage into production.
This is a tricky affair and there are no clean and simple solutions. For eg. when you set up new content in stage as part of a bug fix or minor enhancement, this will be automatically overwritten when you synchronize production content with stage.
Stage environment typically tends to have dozens of items that need to be pushed into production as part of a weekly or biweekly process. We have seen the best way to do this is to synchronize the entire stage DB –> production DB.
In contrast, the development environment tends to have few items (albeit with major functionality) that need to be synced with stage. It is best to manually migrate the relevant content into stage. After testing there, it can be pushed to production as part of the regular processes described above.
We articulated the need for devops rigor in managing both your code and content across the multiple environments.