Strapi vs Directus performance, load tested

Strapi 5 and Directus 11 on the same server, each with Postgres 17, default production config and the same 10 posts, with the same 2,500 simulated users sent at the list items API. This is two of the five CMSes from our CMS load test; the full report also covers Payload, Ghost and WordPress.

Requests a second and p95 as users ramped up

Simulated usersStrapi 5Directus 11
Under 100206 rps, p95 240 ms159 rps, p95 320 ms
About 250287 rps, p95 1.1 s217 rps, p95 1.5 s
About 500290 rps, p95 2.0 s208 rps, p95 3.4 s
About 1,000286 rps, p95 4.1 s208 rps, p95 6.8 s
About 1,500286 rps, p95 6.8 sAll 503, answered in about 0.3 s
2,400 to 2,500279 rps, p95 9.9 sAll 503, answered in about 0.3 s
Whole run133,269 answered, 0 errors49,928 answered, then 503s

The setup

One fresh 4 vCPU / 8 GB server (shared vCPU) per run, with the CMS and Postgres 17 in one docker compose stack. Directus uses its official image. Strapi does not ship one, so it is the stock create-strapi-app project built in production mode. Both got the same 10 posts on first boot. Load came from a second server in the same datacenter and ramped from zero to 2,500 simulated users over 10 minutes. The compose files are at github.com/DevMatei/stresix-showdowns.

The short answer

Strapi served more: about 285 requests a second against about 210 for Directus, and it was quicker at every level both were answering. Both were limited by one Node thread. The bigger difference is what each did once it was full. Strapi kept accepting requests and made them wait, so its p95 climbed to almost 10 seconds without a single error. Directus started turning requests away with an instant 503 at about 1,300 users, just under 4 minutes in.

What ran out

One Node thread at 100% of a core for both, while the server as a whole was about 34% busy under Directus and 39% under Strapi. Postgres stayed at or under 0.3 cores in both runs. Directus used about 1.2 GB of memory and Strapi about 1 GB.

Queue or shed load?

Directus ships with a pressure limiter turned on. When its event loop falls too far behind, it answers 503 straight away instead of letting requests pile up. That keeps the server responsive, makes the failure obvious, and gives a client or proxy something it can retry. Strapi has no limiter by default, so under overload every request gets slow instead of some failing fast. Neither is wrong, but they look very different on a dashboard, so it is worth knowing which one you have before a traffic spike. It is also why the raw Directus peak reads about 3,400 requests a second: the 503s are fast, and the useful number is the 210.

Would a bigger server help?

Not by itself, for the same reason as the rest of the Node CMSes in the test: one core busy, three mostly idle. Run more processes or containers behind a proxy on the same server first. From what one process did here, the reports estimate that 4 processes on this server would comfortably serve about 430 requests a second for Strapi and about 380 for Directus. Those are estimates, so measure again after the change, and check each project's docs for what several instances need. Directus, for example, uses Redis to keep instances in sync.

What this does not tell you

One read only endpoint with 10 posts, one run each, on shared vCPU. Nothing here covers the admin app, writes, permissions, file handling or large collections, and the default response shapes are not identical. p95 is averaged from the run's latency samples, so treat it as approximate.

Frequently asked questions

Is Strapi faster than Directus?

In this test, Strapi held about 285 requests a second on the list API and Directus about 210, on the same server with the same Postgres and default configs. Directus then started returning 503s from its pressure limiter, while Strapi made requests wait instead.

Why does Directus return 503 under load?

Its pressure limiter is on by default. When the Node event loop falls too far behind, Directus answers 503 immediately instead of queueing the request. It can be tuned or turned off in the config, but it is there to protect the server.

Will more CPU make Strapi or Directus faster?

Not on its own. In these runs each one maxed out a single core and left most of the server idle. Run more processes first, then measure again before paying for more cores.

Can I test my own Strapi or Directus setup like this?

Yes. Point Stresix at your repo or compose file and it starts every service on a fresh server, sends the load, and reports what ran out first, per service and per thread. Your first run is free.

Related guides

Stop guessing your specs. Start knowing them.

Point Stresix at a repo or Docker image and get a number you can deploy on, in one run. Your first run is free, no card.

Start a free load test