Directus vs Strapi : Comparing the headless CMS features

Strapi
Directus
20th Jan, 2025
Comparing the Strapi and Directus features

I first published a comparison of Directus and Strapi back in January 2023 based on a CMS evaluation exercise for a project. Since then, this post has evolved via the feedback and questions I have received over a period of time. Also, both Directus and Strapi have evolved in features since then. This post has been rewritten in January 2025 to reflect these changes.

Here’s the single question this post attempts to answer:

How does Directus (11.x) compare to Strapi (5.x) when it comes to catering to various features that are expected from a headless open-source CMS product?

Disclaimer: I’m not affiliated with the creators of Strapi or Directus in any way.

1. Data Engine vs. Headless CMS

Directus and Strapi are fundamentally oriented towards solving different problems. And, understanding this difference in orientation helps us choose the right fit for our requirement.

Directus is a Data Engine. Imagine we already have a database from an employee management system (with tables like employee, management, etc.). Directus can be set up on top of this database to enable us to have headless CMS features to deal with this data. In this way, Directus seeks to be a wrapper of CMS features on top of a database. As a result, it can coexist with other systems on a large backend. Or, it can be introduced on top of a legacy system without requiring data migration into the new setup.

In contrast, Strapi is a code-driven headless CMS. We are required to maintain our schema in the form of JSON files within our Strapi code. Strapi conceals how the data is stored within the underlying database schema and automatically handles synchronizing schema changes in code with the underlying database. This means sharing the database with other sub-systems or directly adopting a legacy database into a Strapi setup is not easily possible.

2. Handling of Database Schema

The difference in the way Strapi and Directus handle the database schema (Strapi - in code vs Directus - in database) affects the following capabilities:

2.1 Migrating from an existing CMS / database: Directus ✅

With Directus’s approach, using it on top of an existing CMS / backend setup / database is simpler. All we do is install Directus, point it to this existing setup, and we are good to go.

In contrast, Strapi requires modeling the existing database schema into Strapi’s schema.json format and then writing custom code to migrate data into the database schema Strapi builds based on the schema.json we created. This makes migrating an existing data setup into Strapi more time-and effort-consuming.

2.2 CMS framework lock-in: Directus ✅

Because Directus just runs on top of the database schema, the issues specific to vendor lock-in are reduced with Directus. To move out of Directus, we simply stop running it on top of our database, and we have our data available as is. With Strapi, unless we decide to leverage Strapi’s schema specifics, we will need to write custom scripts to migrate out of the Strapi CMS setup.

2.3 CMS framework co-living alongside other systems: Directus ✅

Since Directus doesn’t demand any changes to the existing database schema, it can be used for a subset of the tables in a larger backend setup. In this way, it can coexist alongside other systems in a large backend setup. This cannot be done with Strapi since it controls the database schema and actively purges any tables in the underlying database that aren’t reflected in its code schema.json files.

2.4 Making schema changes across environments: Strapi ✅ Directus ✅

With Strapi’s approach, carrying schema changes from one environment to another (eg - dev / staging to production) would simply require running the updated code in the destination environment. But, with Directus, transporting schema changes from one environment to another would require running additional steps (npx directus schema snapshot ./path/to/snapshot.yaml and then npx directus schema apply ./path/to/snapshot.yaml). While Directus requires an additional step to carry schema changes across environments, it is simple enough to be made part of any deployment automation workflow.

3. Versioning the content changes made via the Admin UI Directus ✅

Content versioning enables the content editor to:

  • view earlier versions of an updated record.
  • restore that record back to its earlier version.

Directus always supported viewing content version history and restoring the previous content versions.

With Strapi, version 4 and earlier did not feature content versioning. With v5, Strapi now provides full content versioning. However, it is available only with paid plans - Growth and Enterprise. It is not available with the free Community Edition.

4. Draft and Publish mode for Content Strapi ✅

With v5, Strapi now enables maintaining a published as well as a draft version of any particular record. With this capability, once a record is published, further changes to this record can be maintained in draft mode without affecting the published version. Having two versions of a record always available enables an easy way to preview the changes without affecting the live version.

Directus provides a capability to change the status of a record to Draft, In Review, Published, Archived, etc. to cater to the content publishing workflow. But it does not allow maintaining a published and a non-published version of the same record at the same time. As a result, modifying an already published record requires using workarounds with Directus.

5. File Uploads Strapi ✅

Both Strapi and Directus provide capabilities to upload to various destinations (local path, AWS S3 bucket, etc.). However, there are certain differences that may matter for some implementations:

  • Strapi allows us to write our own custom providers for file uploads (the code would actually upload the files). As a result, if the storage service of our choice isn’t supported by Strapi out-of-the-box, we can simply write our custom provider to make it work. Directus seems to be working in the same direction (see this issue) in the coming future (but the feature hasn’t been prioritized in over a year).
  • Both Strapi and Directus allow us to organize our media uploads into folders. Directus allows us to restrict uploads so that uploads for specific tables go into specific media gallery folders. Strapi also provides granular access control via its RBAC feature (Role-Based Access Control) that also works for media uploads.

With the ability to allow us to code custom providers, Strapi has a slight edge over Directus with respect to the flexibility of coding custom upload logic / rules.

6. Single Sign-on Directus ✅

Both Strapi and Directus provide capabilities to authenticate via various SSO providers (Google, GitHub, Facebook, Okta, etc.). With Strapi, SSO is locked behind the paid plans - Growth and Enterprise. With Directus, a self-hosted setup can implement SSO without paying anything.

But, other than SSO, both Strapi and Directus allow having unlimited users and roles on self-hosted setups without having to pay anything.

7. Dynamic Zones / M2A Relationships Strapi ✅ Directus ✅

Both Strapi and Directus allow us to build records in a table that can contain very different types of data. Think, for example, of a Pages table where each page can contain one or more sections and each section can be of different type (image section, paragraph section, title section, etc.). The ability to build such dynamic records on-the-fly makes content editing very powerful.

With Directus, this can be achieved via M2A (Many-to-any) relationships. And the same can be achieved with Strapi via Dynamic zones.

The Admin UI capabilities for both Strapi and Directus are powerful (allows drag-and-drop reordering of sections, allows inserting new sections anywhere). While these may appear minor nitpicks, I have found content teams heavily rely on these UI capabilities when building dynamic sections.

8. Access Control for Admin UI Features Strapi ✅

With Strapi, Admin UI users are maintained separately from the CMS API users. It allows us to organize the Admin UI users into various roles and configure access control for specific Admin UI screens, collections, plugins, and individual rows of data within the collections.

In fact, Strapi’s Role based Access Control can be setup based on programmatically defined custom rules to restrict certain Admin UI users from accessing certain rows of data. For example, we can create rules so that certain Admin UI users aren’t able to view rows of data in the Salary table for other employees.

With Directus, the only access control available for the Admin UI functionalities is to either allow or disallow a user from accessing it completely. For example - Strapi allows us to create Admin users who have access to the entire Admin setup except Media Library section. But Directus doesn’t have any such capability to let a user have Admin access without access to the File Library section.

9. CRUD APIs features Strapi ✅ Directus ✅

Both Strapi and Directus provide API parameters to adequately filter, sort, paginate, and limit the data as required. Directus also has additional API parameters to aggregate and group the data queried via its Rest APIs. Also, we can use GraphQL to fetch data from the CMS system with both Strapi and Directus.

10. Access-control for APIs Strapi ✅ Directus ✅

Both Strapi and Directus allow us to configure roles to have access to specific tables. With Directus, a very fine-grained access control can be setup to enable specific roles to have access to only specific rows of data in a table (e.g., allow access to only those records where the field currency has value USD). While the same cannot be done from the Strapi Admin UI, we can use Strapi middlewares to code this access-control logic.

11. Internationalization Strapi ✅ Directus ✅

Both Strapi and Directus provide features to maintain records in more than one language. Both also provide API parameters to ask for records only in a specific language.

Strapi treats locale as a separate field and allows us to query, access control, etc. based on this. Similarly, Directus has a special translations field to enable storing the records in multiple languages.

12. Customizing the CRUD API Behavior Strapi ✅ Directus ✅

Both Strapi and Directus provide hooks for us to write custom code that gets executed when the CRUD APIs for our content are invoked. So, customizations like the following can be implemented with both:

  • Modifying API requests / responses as needed
  • Building custom input validations.
  • Emailing someone when a certain record has a certain value.

However, there is an important distinction between the two:

  • Strapi provides a global strapi object everywhere that can be used to access any data (eg : strapi.documents('api::blog.blog').findOne()).
  • With Directus, we need to call the APIs to access any data.

In some situations, the Directus approach can be less flexible and force us to expose certain data via an API to implement specific customizations. While we can keep such APIs secure behind authentication, this is still less secure than the Strapi approach, which does away with a need to expose the APIs to access data for implementing hooks or other customizations.

13. Extending the CMS functionality Strapi ✅ Directus ✅

Both Strapi and Directus allow us to build the following:

  • Custom fields
  • Custom Admin UI screens.
  • Custom API endpoints

With the above, we can extend the CMS functionality as desired. However, the UI frameworks leveraged by the two CMS is different. Directus requires us to write the Admin UI code with vue.js whereas Strapi requires us to write the Admin UI code with react.js.

14. Popularity Strapi ✅

As of Jan 2025, the package @strapi/strapi has ~130k weekly downloads in comparison to ~12k weekly downloads for the directus package. Also, as per npmtrends comparison, @strapi/strapi shows a higher growth in the last 2 years.

Directus & Strapi - trend of package downloads per week

15. License Terms and Fees Directus ✅

Strapi provides a Community Edition that can be self-hosted without payment of any fees. However, two prominent features that are not available with this free edition are Content Versioning and Single Sign-On (SSO).

Like Strapi, a self-hosted version of Directus can be run without payment of any fees. But, unlike Strapi, the free version of self-hosted Directus encompasses all the features and is not restricted in any way. Directus expects us to buy its license only if our annual revenue is more than $5M.

For cloud versions, both Strapi and Directus have multiple plans with specific fees per user per month. In general, Directus cloud plans are less expensive than Strapi cloud plans.

Conclusion

When comparing Directus and Strapi features, licensing fees and setup options, there is no clear winner. As a result, the key to making an informed choice is to identify our must have features and let them drive our choice:

“We have an existing database (or backend setup), and we seek to have a Rest APIs / GraphQL / Admin UI for our data.” Pick Directus.

“We have a large Admin UI team across departments and need a fine-grained access control for our Admin UI screens and features.” Pick Strapi.

“We don’t know what all we may need, but we feel safer adopting something more popular.” Pick Strapi.

“We do not want our data to be locked into a CMS-specific schema.” Pick Directus.

Punit Sethi
Punit Sethi
My tryst with Headless CMS frameworks:

Back in 2017, I started working as an independent web performance specialist for React frontends. Over the years, a few of the teams where I worked for long were kind enough to let me help solve their CMS issues.

Fast forward to now, I have worked with multiple teams to choose the right CMS framework and then setup + implement the chosen solution.

To discuss your CMS specific pain points, email me at punit@tezify.com.


Copyright (c) 2017-2025 Tezify All Rights Reserved. Created in India. GSTIN : 24BBQPS3732P1ZW.