Headless CMSs go head to head: Strapi vs DatoCMS

Strapi is an open source headless CMS. Its main benefits are solid migrations, option to self host and excellent extensibility. In this blog post, we compare Strapi to our favourite headless CMS: DatoCMS.

Our verdict is that Strapi is the best choice if you want to bring your own database and hosting or need severe UI customisation. For most straightforward projects without specific requirements however, we think DatoCMS is a better choice. Let’s dive in!

strapi vs dato pros and cons

Hosting: do-it-yourself vs cloud

DatoCMS is a pure cloud service. Strapi, on the other hand, offers a self hosted solution as well as Strapi Cloud, their cloud solution. Self hosted can either mean that you install the software on your own on-premise server or a server in a managed cloud. 

So when should you consider self hosting? 

  • You have outgrown the current plan of the cloud service and the larger plan is too expensive or restrictive
  • You have specific privacy requirements and don’t want to introduce another third-party
  • You want to save costs by using your existing fleet of servers and an inhouse team of devops
  • Or maybe you just need something very flexible and you want something that can be customized from the ground up

In conclusion, self hosting is a very specific demand. If your requirements don’t permit cloud hosting, look no further: Dato doesn’t do self hosting. If you can go either way, the benefits to cloud hosting are huge in terms of not having to take responsibility for technical stuff, but that comes at a (monetary) cost. The middle ground is a managed cloud: the flexibility of self-hosting with the benefit of zero maintenance.

Migrations: model representation in JSON vs migration scripts

As a developer you spend lots of time creating and improving the data model of your cms. This is important because the data model determines how your content is structured and how it can be retrieved through an API.

Modeling your CMS through a user interface is friendly, quick and intuitive. Yet, once your model becomes more complex, you’ll want to have that model represented in code. Code is easier to base migrations on, goes along well with documentation and benefits from all the advantages of version control including code reviews, history, mitigating code conflicts etcetera.

Recently, DatoCMS introduced migrations support in their developer tooling. This was a very welcome feature to us and has quickly become the de facto standard to implement new instances for new projects for us. Via the CLI, Dato can generate migrations based on changes you make (or made, before switching to scripted migrations) in the admin UI. A typical migration for DatoCMS looks like this:

module.exports = async (client) => {
  const pageModel = await client.itemTypes.create({
    name: 'Page',
    api_key: 'page',

  const titleField = await client.fields.create(pageModel, {
    api_key: 'title',
    label: 'Title',
    field_type: 'string',
    localized: true,
    validators: {
      required: {},


Although on the surface there doesn’t seem to be a problem with this, in practice we spend a lot of time on writing and testing these migrations. Sadly, DatoCMS has cryptic error messages when your migrations are somehow ‘wrong’, and they can fail partially. To be fair, we didn’t use the generated migrations much yet — they might be a big improvement. But yes, hand coded migrations were hard and exhausting to get right.

Strapi does this differently and much better in our opinion. After creating a new model (in the admin UI), Strapi generates JSON files describing your model. These files are actual representations of your models, and not migrations: Strapi migrates to and from in the background. Changes in your models are just like code changes: you’ll find them in your git history. These files look something like this:

  "kind": "collectionType",
  "collectionName": "pages",
  "info": {
    "singularName": "page",
    "pluralName": "pages",
    "displayName": "Page"
  "options": {
    "draftAndPublish": true
  "pluginOptions": {},
  "attributes": {
    "Title": {
      "type": "string"

Equally important to its very comprehensible setup, is that the data model can only be changed during development. There’s a Content-Type editor that is deliberately not available on a production environment of the Strapi CMS. This isn’t the case for DatoCMS, where an admin can make changes to the model being used in production.

In conclusion, scripted migrations are available in Strapi as well as DatoCMS. The Strapi way is reliable and crystal clear: you define models, migrations are taken care of by Strapi. DatoCMS puts it all in your hands, which may seem more flexible, but it’s also more error prone.

Extensibility: integrated React components vs iframe embeds

Sometimes the default fields in a CMS “don’t cut it” and you want something different to provide more flexibility. For example, you might want to grab data from an external service or present content in a certain way. DatoCMS supports plugins, which you can make yourself, or you can install them from the marketplace.

While working great for simple use cases, DatoCMS plugins have limited functionality. If you want something more complex, things soon start to become hacky and prone to breaking down.. This is because the plugins are built as separate web apps, using the Dato Plugin SDK and an API key, and are embedded as iframes. They have access to the data model, but not the surrounding page.

These limitations don’t apply to Strapi. Plugins in Strapi are a first class citizen and part of the source code. Developers are able to change any part of the CMS. Don’t like the built-in fields? Build your own. Want to whitelabel the admin ui, no problem!

Custom fields and interfaces are built as React components. Your custom components are tightly integrated within the admin UI through the use of the Strapi design system.

A screenshot of strapi cms with a map and color picker
By default Strapi does not have a Map or Color field option like Dato CMS does. Using the plugin system we were able to quickly make our own.

We have built many plugins for Dato, and use other community plugins on a daily basis. However, being able to extend Strapi at the code level is a lot more efficient and allows us to present a seamless experience for the end user.

Branch previews: separate deployments vs environments

We often work with preview environments so we can demonstrate what we’ve been working on in a Pull Request, without having to change anything in production. Often these changes are also accompanied by changes to the data model of our CMS. So this means that our CMS should be able to provide preview environments entirely separated from the production environment. 

Luckily, Dato CMS provides this feature through the aptly named “environments”. Through this feature it is possible to create a sandbox in which we can try out new model changes.

Unfortunately, at the time of writing, Strapi does not support a similar feature. Supporting such a feature would probably mean running multiple Strapi instances and database instances. Of course, if you are naively launching multiple servers for each environment, that would increase costs dramatically. .

We have been toying with the idea of running multiple preview instances of Strapi on one server (using Docker on AWS ECS) accompanied by a file based database (something like SQLite on EFS) instead of a separate database server. This would decrease the cost of running multiple Strapi CMS instances a lot. To decrease costs even more you can schedule a script to shutdown the preview servers outside of office hours. Deploying those branch builds and keeping stuff in sync is a whole other storey, however.

Bottom line: showing feature previews that include data model changes to a client becomes a lot harder when using Strapi as opposed to leveraging DatoCMS environments.


Headless CMSs (like DatoCMS, but we have experience with Contentful, headless Wordpress, Sanity and others) usually provide a great set of tools that satisfy every developer’s and client’s  needs. Alternatively, you can get closer to the metal, customise to your heart’s content and control hosting and deployments by picking the excellent Strapi.

← All blog posts

Want to know more about headless CMSs?

Looking for a demo of our setups, an architecture review, or just want to talk about this more?

Read about our serivce