Contentful's environment model

How it works and why it's awesome

6 September 2021

I have been working on a new project called Migrateful, a migration manager for the Contentful platform. As a result, I have developed an appreciation for Contentful's environment system. It leverages the potential of cloud provisioning and offers major advantages. However, it is a bit different from the traditional staging environments that most developers are accustomed. So, it's worth taking a minute to understand how the environment system works and how it can be utilized effectively.

Spaces

The Contentful system is formed by a hierarchy of Organization -> Space -> Environment. A space is equivalent to a project, and within each space you can have multiple environments. When you first create an empty space, there is a default, master environment where you can start defining your schemas and inserting data.

Environments

You can think of an environment as an ephemeral bucket where you store all of your types and content. They can be easily created by cloning (or copying) your master environment into new environment. The new environment will contain all of the same types and content until you begin making changes. These changes will only affect the new environment and are completely isolated from the original cloned environment. A new environment can be just as easily deleted, removing any modifications made there.

New environments can only be cloned from the master environment. This effectively copies everything from the master including all of the data. This means that large environments with lots of content may take a while to clone. However, I suspect that Contentful uses a shallow copy during the clone, and lazily makes a deep copy of individual pieces of content as changes are made within a specific environment.

Aliases

One more piece of Contentful's environments that deserves explanation is the "alias" system. An alias is used to declare, or tag, an environment for a particular type of usage. For example, it is typical to have a "master" alias that points to your current production environment. Then, promoting a new environment to production is simply a matter of re-aliasing.

I think of aliases as pointers. For those who are familiar with the C-language, an alias is like a persisted variable that "points" to a environment, and can be updated to point to newer ones.

Example usage

I will use an example of how you can setup and use your environments to bring all these concepts togther and make the most of this system.

contentful-diagram

In the diagram above, you start out with a master environment. I prefer to name my production environments with release-{version}. So, I clone the master environment, name the new one release-01, and setup a master alias to point there. Now, I want to develop a new feature, so I clone the production environment into a feature environment. After making some changes, I decide to go in a different direction. So, I delete my old feature environment and clone a new one. Note that only the master environment can be cloned. Once I am done, I will rename my feature environment to release-02 and point the master alias there. Now, all of my application traffic will be routed to the new release environment.

Note how this is different from a the typical engineering environment. Typically you would provision (probably by hand) two environments. One for production and one for staging. These environments would persist forever, and you would deploy new types, data, and features to each one as the system evolves. A massive disadvantage with this approach is that the two environments have a tendency to drift apart. Small differences between the two will go unnoticed during development until at some point when deploying to production and the feature does not behave as it did during development.

With Contentful's environment system, every new environment is cloned from the production environment. This makes it very easy to keep your development environment in parity with production.

It is a massive advantage of cloud systems that we can provision an entirely new environment to look exactly like production (with production data) in less than a minute!

Migration system

There is a subtle (and important) point to be made here. When I am ready to publish my new feature, there are two approaches to getting these changes into production.

  • promote the feature environment to be the production environment (re-alias)
  • re-clone the master, apply my desired changes to the fresh environment, and then alias the new environment to be production

I prefer the second approach because it prevents any accidental changes that were made in the development environment from making it into production. However, this approach requires being able to execute the desired changes reproducably using code that can be automatically applied to environments. This is functionality that I have built using Contentful's migration SDK and packaged into the npm project migrateful. I plan to talk more about this in an upcoming article.

https://www.npmjs.com/package/migrateful