Directus vs Strapi : Comparing the headless CMS features

For the past couple of years, I have worked with multiple teams to customize a certain headless open source CMS product to their specific requirements. I must admit that most of this experience has been with Strapi. In contrast, I’ve had only a few weeks of experience with Directus CMS. I’m hoping that gives me enough perspective to evaluate the following:
How does Directus (9.x) compare to Strapi (4.x) when it comes to catering to various features that are expected from a headless open-source CMS product?
I’ll use this post to answer this question.
Disclaimer : I’m not affiliated to the creators of Strapi or Directus in any way.
1. Handling of Database Schema
With Strapi, the database schema is maintained within the code (specifically the schema.json
files). Whenever a Strapi CMS instance is started, the CMS code ensures that the schema within the database is in sync with what is specified in the schema.json
files.
In contrast, Directus calls itself a Data platform
. With Directus, the database schema is maintained only inside the database. The schema is not reflected within the code. In this way, Directus is more of a wrapper of CMS features on top of this database schema.
1.1 How does this difference of handling database schema affect things?
-
Migrating from an existing CMS / database: Directus ✅
With Directus’s approach, migrating from an existing CMS / database should be simpler. We should be able to directly build CMS features on top of the existing database. In contrast, Strapi would require modelling the existing schema into Strapi’sschema.json
format and then writing custom code to migrate data into the Strapi CMS setup. -
Carrying schema changes across environments: Strapi ✅ Directus ✅
With Strapi’s approach, carrying schema changes from one environment to another (eg -dev
/staging
toproduction
) 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 thennpx 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. -
CMS vendor 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. This will require more effort than doing the same with Directus.
2. 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 it’s earlier version.
As of Strapi 4.10, there is no way to view or restore an updated record back to it’s earlier version. With Directus, we can view the version history of a record and restore it back to any of the previous versions.
However, with 4.6, Strapi introduced the export-import feature which allows us to export specific rows of data from one Strapi CMS setup to another. This way, we can add a certain data in non-production Strapi CMS environments and import them to the production Strapi CMS environment as and when needed.
3. File Uploads Strapi ✅ Directus ✅
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.
- Both Strapi and Directus allow us to organize our media uploads into folders. But, Directus does this better by allowing us to restrict uploads for a certain tables going into certain media gallery folders. This can help keep media uploads organized with larger teams.
4. Single Sign-on Directus ✅
Both Strapi and Directus provide capabilities to authenticate via various SSO providers (Google, Github, Facebook, Okta, etc). But, with Strapi - SSO is locked behind the Gold Plan
which is priced as Contact Us
(read Expensive
!). 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.
5. 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, a pages table where each page can contain one or more sections and each section can be of differen type (image section, paragraph section, title section, etc). Ability to build such dynamic records on-the-fly can make content editing very powerful.
Within Directus, this can be achieved via M2A (Many-to-any) relationships. The same can be achieved with Strapi via Dynamic zones. The Strapi Admin UI is more polished in implementing this given that it allows us to re-order the components within the dynamic zones. But, other than this minor nitpick - both the CMS offer this feature on-par.
6. Access Control for Admin UI Strapi ✅
With Strapi, Admin UI users & the CMS API users are maintained in separate tables. Strapi also allows us to add Admin roles with a capability to configure access control to various admin screens, collection types, plugins.
Directus maintains a single table to handle both - Admin UI & CMS API users. While it allows creating as many roles as we like, the only access control available for the Admin UI functionalities is to either allow or disallow it completely.
So, for places where multiple teams intend to use the CMS Admin UI, there is no built-in way to access control certain parts of the CMS Admin UI.
7. CRUD APIs features Strapi ✅ Directus ✅
Both Strapi and Directus provide API parameters to adequately filter, sort, paginate, limit the data as required. Directus also has additional API parameters to aggregate & group the data queried via it’s Rest APIs.
8. Access-control for APIs Strapi ✅ Directus ✅
Both Strapi and Directus allow us to configure roles to have access to specific tables. Directus provides a more fine-grained control here since it allows us to let the roles have access to only specific records of a table (eg: allow access to only those records where the field currency
has value USD
). Strapi does not allow row-level access control for the APIs.
9. Internationalization Strapi ✅ Directus ✅
Both Strapi and Directus provide features to maintain records in more than one languages. Both also provide API parameters to ask for records only in a specific language.
Strapi treats locale
as a seprate field and allows us to query, access control, etc based on this. Directus treats language
as one more field for a collection that can be have a language value as needed.
10. 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 which can be used to access any data (eg :strapi.entityService.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.
11. 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
.
12. Popularity Strapi ✅
As of May 2023, the package @strapi/strapi
has ~55k weekly downloads in comparison to ~6k weekly downloads for the directus
package. Also, as per npmtrends comparison, @strapi/strapi
shows an increase in the downloads over the last 1 year.

Note: Some of the Strapi trend above could be folks moving from the old strapi
(3.x) package to the new @strapi/strapi
(4.x) package but despite that, the absolute numbers suggest a wider Strapi adoption.
Conclusion
When comparing Directus and Strapi features, there is no clear winner. Each is better than the other at certain features. As a result, identifying the must have
features helps us know the requirements that can drive our choice. Example -
“We absolutely need content versioning.” - pick Directus.
“We need fine grained access control for our Admin UI screens and features.” - pick Strapi.
“We need Single Sign-On (SSO) but cannot pay enterprise license cost.” - pick Directus.
“We don’t know what all we may need but we feel safer adopting something more popular.” - pick Strapi.

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.