rest-api-performance

Created: December 2023

Introduction

Over the last year I have written REST APIs with various technologies and wanted to compare some of them. I created 5 identical clients with Elysia, Express, Rocket, Phoenix and Flask. I tested them on the simplest endpoint /get which returns a "Hello World" text message.

Each tested locally on a 2023 Macbook Air M2.

I used Ali for generating 10000 requests per second for each client.

Technologies

Node, JavaScript, Express

  • Node: 20.5.1
  • Express: 4.18.2

Bun, TypeScript, Elysia

  • Bun: 1.0.18
  • Elysia: 0.7.30

Python, Flask, Bjoern

  • Python: 3.11.5
  • Flask: 3.0.0
  • Bjoern: 3.2.2

Rust, Rocket

  • Rust: 1.74.0
  • Rocket: 0.5.0

Erlang, Elixir, Phoenix

  • Erlang: 26
  • Elixir: 1.15.7
  • Phoenix: 1.7.10

Test details

Each test was run for 10 minutes with 10000 requests per second which approximately sums up to 6 000 000 requests in total.

status code 200status code 0success ratetotal latency
rocket599999370,9999988312m 12s
elysia5999949510,9999915017m 41s
flask59998521480,9999753321m 54s
phoenix599877812220,9997963320m 50s
express599884011590,9998068332m 5s

Above are the most interesting results from all the runs. You can see whole reports here.

Rust

Rust with Rocket is clearly and unsurprisingly a winner. Rocket still is quite some time away from the 1.0 release but it already should be production ready.

JS/TS Bun Node

It is worth noting that technically Elysia and Express are both JavaScript frameworks, the main difference is with runtimes used to run the code. BunJS is a modern JS/TS runtime for which Elysia is optimized for. Express traditionally is run on NodeJS.

With Express ran on Bun we can see that it’s Bun doing most of the heavy-lifting:

status code 200status code 0success ratetotal latency
elysia5999949510,9999915017m 41s
bun express59996573430,9999428320m 19s
node express599884011590,9998068332m 5s

Python

How is Python that fast? It isn’t, Bjoern is a WSGI server written with C. I tried running Flask with Waitress first, a WSGI server recommended by the Flask team in the official docs, but the results were stunningly bad:

status code 200status code 0success ratetotal latency
flask bjoern59998521480,9999753321m 54s
flask waitress5927382726180,9878970017h 8m 8s

Elixir

Phoenix has been a disappointment on every side. It didn’t deliver with stability nor speed. It is a REST framework, but it is designed for fullstack web applications. Generating a bare REST project is cumbersome and not very effective in the end (as you can see by comparing the language chart in this repo, Elixir projects are bloated).

To generate a regular phoenix project the following command is used:

mix phx.new

I had to use this one:

mix phx.new --no-ecto --no-assets --no-dashboard --no-html --no-live --no-mailer

It might work great for bigger projects but for this experiment it was an overkill.