A 2025 benchmark of main Web API frameworks
Table of Contents
The contenders #
Framework & Source code | Runtime | ORM |
---|---|---|
Laravel 11 (api / image) | FrankenPHP 8.4 | Eloquent |
Symfony 7.2 (api / image) | FrankenPHP 8.4 | Doctrine |
FastAPI (api / image) | Python 3.13 | SQLAlchemy 2.0 |
NestJS 10 (api / image) | Node 22 | Prisma 6 |
Spring Boot 3.4 (api / image) | Java 21 | Hibernate 6 |
ASP.NET Core 9 (api / image) | .NET 9.0 | EF Core 9 |
The Swarm cluster for testing #
Here is the complete terraform swarm bootstrap if you want to reproduce the same setup.
App deployment configurations #
version: "3.8"
services:
app:
image: gitea.okami101.io/conduit/laravel:latest
environment:
- APP_KEY=base64:nltxnFb9OaSAr4QcCchy8dG1QXUbc2+2tsXpzN9+ovg=
- DB_CONNECTION=pgsql
- DB_HOST=postgres_db
- DB_USERNAME=okami
- DB_PASSWORD=okami
- DB_DATABASE=conduit_laravel
- JWT_SECRET_KEY=c2b344e1-1a20-47fc-9aef-55b0c0d568a7
networks:
- postgres_db
- traefik_public
deploy:
labels:
- traefik.enable=true
- traefik.http.routers.laravel.entrypoints=websecure
- traefik.http.services.laravel.loadbalancer.server.port=8000
replicas: 2
placement:
max_replicas_per_node: 1
constraints:
- node.labels.run == true
networks:
postgres_db:
external: true
traefik_public:
external: true
version: "3.8"
services:
app:
image: gitea.okami101.io/conduit/symfony:latest
environment:
- APP_SECRET=ede04f29dd6c8b0e404581d48c36ec73
- DATABASE_URL=postgresql://okami:okami@postgres_db/conduit_symfony
- DATABASE_RO_URL=postgresql://okami:okami@postgres_db/conduit_symfony
- JWT_PASSPHRASE=c2b344e1-1a20-47fc-9aef-55b0c0d568a7
networks:
- postgres_db
- traefik_public
deploy:
labels:
- traefik.enable=true
- traefik.http.routers.symfony.entrypoints=websecure
- traefik.http.services.symfony.loadbalancer.server.port=80
replicas: 2
placement:
max_replicas_per_node: 1
constraints:
- node.labels.run == true
networks:
postgres_db:
external: true
traefik_public:
external: true
version: "3.8"
services:
app:
image: gitea.okami101.io/conduit/fastapi:latest
environment:
- DB_HOST=postgres_db
- DB_RO_HOST=postgres_db
- DB_PORT=5432
- DB_USERNAME=okami
- DB_PASSWORD=okami
- DB_DATABASE=conduit_fastapi
- JWT_PASSPHRASE=c2b344e1-1a20-47fc-9aef-55b0c0d568a7
networks:
- postgres_db
- traefik_public
deploy:
labels:
- traefik.enable=true
- traefik.http.routers.fastapi.entrypoints=websecure
- traefik.http.services.fastapi.loadbalancer.server.port=8000
replicas: 4
placement:
max_replicas_per_node: 2
constraints:
- node.labels.run == true
networks:
postgres_db:
external: true
traefik_public:
external: true
version: "3.8"
services:
app:
image: gitea.okami101.io/conduit/nestjs:latest
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://okami:okami@postgres_db/conduit_nestjs
- JWT_SECRET=c2b344e1-1a20-47fc-9aef-55b0c0d568a7
networks:
- postgres_db
- traefik_public
deploy:
labels:
- traefik.enable=true
- traefik.http.routers.nestjs.entrypoints=websecure
- traefik.http.services.nestjs.loadbalancer.server.port=3000
replicas: 2
placement:
max_replicas_per_node: 1
constraints:
- node.labels.run == true
networks:
postgres_db:
external: true
traefik_public:
external: true
version: "3.8"
services:
app:
image: gitea.okami101.io/conduit/spring-boot:latest
environment:
- SPRING_PROFILES_ACTIVE=production
- DB_HOST=postgres_db
- DB_PORT=5432
- DB_RO_HOST=postgres_db
- DB_USERNAME=okami
- DB_PASSWORD=okami
- DB_DATABASE=conduit_springboot
- JWT_SECRET_KEY=YzJiMzQ0ZTEtMWEyMC00N2ZjLTlhZWYtNTViMGMwZDU2OGE3
networks:
- postgres_db
- traefik_public
deploy:
labels:
- traefik.enable=true
- traefik.http.routers.springboot.entrypoints=websecure
- traefik.http.services.springboot.loadbalancer.server.port=8080
replicas: 2
placement:
max_replicas_per_node: 1
constraints:
- node.labels.run == true
networks:
postgres_db:
external: true
traefik_public:
external: true
version: "3.8"
services:
app:
image: gitea.okami101.io/conduit/symfony:latest
environment:
- SERVER_NAME=:80
- APP_SECRET=ede04f29dd6c8b0e404581d48c36ec73
- DATABASE_DRIVER=pdo_pgsql
- DATABASE_URL=postgresql://okami:okami@postgres_db/conduit_symfony
- DATABASE_RO_URL=postgresql://okami:okami@postgres_db/conduit_symfony
- JWT_PASSPHRASE=c2b344e1-1a20-47fc-9aef-55b0c0d568a7
- FRANKENPHP_CONFIG=worker ./public/index.php
- APP_RUNTIME=Runtime\FrankenPhpSymfony\Runtime
networks:
- postgres_db
- traefik_public
deploy:
labels:
- traefik.enable=true
- traefik.http.routers.symfony.entrypoints=websecure
- traefik.http.services.symfony.loadbalancer.server.port=80
replicas: 2
placement:
max_replicas_per_node: 1
constraints:
- node.labels.run == true
networks:
postgres_db:
external: true
traefik_public:
external: true
The k6 scenarios #
Scenario 1 - Database intensive #
import http from "k6/http";
import { check } from "k6";
export const options = {
scenarios: {
articles: {
env: { CONDUIT_URL: '<framework_url>' },
duration: '1m',
executor: 'constant-arrival-rate',
rate: '<rate>',
timeUnit: '1s',
preAllocatedVUs: 50,
},
},
};
export default function () {
const apiUrl = `https://${__ENV.CONDUIT_URL}/api`;
const limit = 10;
let offset = 0;
let articles = []
do {
const articlesResponse = http.get(`${apiUrl}/articles?limit=${limit}&offset=${offset}`);
check(articlesResponse, {
"status is 200": (r) => r.status == 200,
});
articles = articlesResponse.json().articles;
offset += limit;
}
while (articles && articles.length >= limit);
}
The expected pseudocode SQL queries to build this response:
SELECT * FROM articles LIMIT 10 OFFSET 0;
SELECT count(*) FROM articles;
SELECT * FROM users WHERE id IN (<articles.author_id...>);
SELECT * FROM article_tag WHERE article_id IN (<articles.id...>);
SELECT * FROM favorites WHERE article_id IN (<articles.id...>);
Scenario 2 - Runtime intensive #
import http from "k6/http";
import { check } from "k6";
export const options = {
scenarios: {
articles: {
env: { CONDUIT_URL: '<framework_url>' },
duration: '1m',
executor: 'constant-arrival-rate',
rate: '<rate>',
timeUnit: '1s',
preAllocatedVUs: 50,
},
},
};
export default function () {
const apiUrl = `https://${__ENV.CONDUIT_URL}.sw.okami101.io/api`;
const limit = 10;
let offset = 0;
const tagsResponse = http.get(`${apiUrl}/tags`);
check(tagsResponse, {
"status is 200": (r) => r.status == 200,
});
let articles = []
do {
const articlesResponse = http.get(`${apiUrl}/articles?limit=${limit}&offset=${offset}`);
check(articlesResponse, {
"status is 200": (r) => r.status == 200,
});
articles = articlesResponse.json().articles;
for (let i = 0; i < articles.length; i++) {
const article = articles[i];
const articleResponse = http.get(`${apiUrl}/articles/${article.slug}`);
check(articleResponse, {
"status is 200": (r) => r.status == 200,
});
const commentsResponse = http.get(`${apiUrl}/articles/${article.slug}/comments`);
check(commentsResponse, {
"status is 200": (r) => r.status == 200,
});
const authorsResponse = http.get(`${apiUrl}/profiles/${article.author.username}`);
check(authorsResponse, {
"status is 200": (r) => r.status == 200,
});
}
offset += limit;
}
while (articles && articles.length >= limit);
}
The results #
Laravel (Octane) #
Laravel scenario 1 #
Iteration creation rate = 10/s
checks.........................: 100.00% 27540 out of 27540
data_received..................: 294 MB 4.7 MB/s
data_sent......................: 2.4 MB 38 kB/s
dropped_iterations.............: 61 0.968024/s
http_req_blocked...............: avg=37.97µs min=266ns med=836ns max=78.96ms p(90)=1.45µs p(95)=1.64µs
http_req_connecting............: avg=2.01µs min=0s med=0s max=4.05ms p(90)=0s p(95)=0s
http_req_duration..............: avg=95.87ms min=5.15ms med=49.14ms max=294.56ms p(90)=193.99ms p(95)=202.61ms
{ expected_response:true }...: avg=95.87ms min=5.15ms med=49.14ms max=294.56ms p(90)=193.99ms p(95)=202.61ms
http_req_failed................: 0.00% 0 out of 27540
http_req_receiving.............: avg=571.32µs min=28.45µs med=490.81µs max=33.61ms p(90)=864.61µs p(95)=1.13ms
http_req_sending...............: avg=104.98µs min=23.57µs med=89.96µs max=18.26ms p(90)=155.83µs p(95)=179.54µs
http_req_tls_handshaking.......: avg=32.54µs min=0s med=0s max=38.93ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=95.19ms min=4.92ms med=48.47ms max=294.04ms p(90)=193.26ms p(95)=201.93ms
http_reqs......................: 27540 437.03919/s
iteration_duration.............: avg=4.93s min=1.31s med=5.22s max=7.16s p(90)=6.21s p(95)=6.39s
iterations.....................: 540 8.569396/s
vus............................: 3 min=3 max=50
vus_max........................: 50 min=50 max=50
Laravel scenario 2 #
Iteration creation rate = 1/s
checks.........................: 100.00% 66291 out of 66291
data_received..................: 153 MB 1.7 MB/s
data_sent......................: 5.5 MB 61 kB/s
dropped_iterations.............: 2 0.02222/s
http_req_blocked...............: avg=14.62µs min=224ns med=807ns max=127.73ms p(90)=1.41µs p(95)=1.57µs
http_req_connecting............: avg=998ns min=0s med=0s max=14.85ms p(90)=0s p(95)=0s
http_req_duration..............: avg=45.94ms min=3.38ms med=34.14ms max=960.12ms p(90)=98.44ms p(95)=109.67ms
{ expected_response:true }...: avg=45.94ms min=3.38ms med=34.14ms max=960.12ms p(90)=98.44ms p(95)=109.67ms
http_req_failed................: 0.00% 0 out of 66291
http_req_receiving.............: avg=243.23µs min=20.25µs med=159.9µs max=20.5ms p(90)=462.34µs p(95)=596.36µs
http_req_sending...............: avg=97.49µs min=13.22µs med=83.1µs max=19.68ms p(90)=147.69µs p(95)=173.01µs
http_req_tls_handshaking.......: avg=10.86µs min=0s med=0s max=25.13ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=45.6ms min=0s med=33.78ms max=959.32ms p(90)=98.1ms p(95)=109.33ms
http_reqs......................: 66291 736.482032/s
iteration_duration.............: avg=50.62s min=29.31s med=51.94s max=1m12s p(90)=1m9s p(95)=1m11s
iterations.....................: 17 0.188867/s
vus............................: 42 min=1 max=50
vus_max........................: 50 min=50 max=50
Symfony (FrankenPHP) #
Symfony scenario 1 #
Iteration creation rate = 10/s
checks.........................: 100.00% 26826 out of 26826
data_received..................: 242 MB 3.8 MB/s
data_sent......................: 2.3 MB 37 kB/s
dropped_iterations.............: 74 1.173916/s
http_req_blocked...............: avg=45µs min=231ns med=852ns max=121.78ms p(90)=1.48µs p(95)=1.66µs
http_req_connecting............: avg=2.37µs min=0s med=0s max=6.04ms p(90)=0s p(95)=0s
http_req_duration..............: avg=100.68ms min=7ms med=77.39ms max=241.69ms p(90)=182.09ms p(95)=191.03ms
{ expected_response:true }...: avg=100.68ms min=7ms med=77.39ms max=241.69ms p(90)=182.09ms p(95)=191.03ms
http_req_failed................: 0.00% 0 out of 26826
http_req_receiving.............: avg=571.25µs min=29.27µs med=483.38µs max=17.75ms p(90)=888.77µs p(95)=1.19ms
http_req_sending...............: avg=106.3µs min=24.84µs med=91.61µs max=7.88ms p(90)=158.49µs p(95)=184.03µs
http_req_tls_handshaking.......: avg=37.23µs min=0s med=0s max=30.9ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=100ms min=6.85ms med=76.72ms max=241.35ms p(90)=181.42ms p(95)=190.3ms
http_reqs......................: 26826 425.56044/s
iteration_duration.............: avg=5.17s min=1.05s med=5.55s max=7.22s p(90)=6.21s p(95)=6.35s
iterations.....................: 526 8.344322/s
vus............................: 3 min=3 max=50
vus_max........................: 50 min=50 max=50
Symfony scenario 2 #
Iteration creation rate = 2/s
checks.........................: 100.00% 138128 out of 138128
data_received..................: 245 MB 3.1 MB/s
data_sent......................: 11 MB 137 kB/s
dropped_iterations.............: 31 0.387655/s
http_req_blocked...............: avg=7.88µs min=183ns med=685ns max=83.34ms p(90)=1.25µs p(95)=1.43µs
http_req_connecting............: avg=385ns min=0s med=0s max=4.45ms p(90)=0s p(95)=0s
http_req_duration..............: avg=20.55ms min=2.07ms med=18.03ms max=259.05ms p(90)=38.46ms p(95)=43.95ms
{ expected_response:true }...: avg=20.55ms min=2.07ms med=18.03ms max=259.05ms p(90)=38.46ms p(95)=43.95ms
http_req_failed................: 0.00% 0 out of 138128
http_req_receiving.............: avg=415.85µs min=15.14µs med=177.95µs max=39.61ms p(90)=740.65µs p(95)=1.39ms
http_req_sending...............: avg=92.45µs min=15.6µs med=71.73µs max=19.02ms p(90)=137.18µs p(95)=168.9µs
http_req_tls_handshaking.......: avg=6.07µs min=0s med=0s max=34.16ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=20.04ms min=0s med=17.5ms max=258.94ms p(90)=37.81ms p(95)=43.25ms
http_reqs......................: 138128 1727.291662/s
iteration_duration.............: avg=32.23s min=13.15s med=34.27s max=41.48s p(90)=40.76s p(95)=41.1s
iterations.....................: 89 1.112946/s
vus............................: 8 min=2 max=50
vus_max........................: 50 min=50 max=50
Huge gap in performance against Laravel Octane here, about twice better ! Without FrankenPHP, we were capping to previously about 300 req/s on Apache…
FastAPI #
As a side note here, uvicorn is limited to 1 CPU core, so I use 2 replicas on each worker to use all CPU cores.
FastAPI scenario 1 #
Iteration creation rate = 15/s
checks.........................: 100.00% 39678 out of 39678
data_received..................: 321 MB 5.2 MB/s
data_sent......................: 3.4 MB 55 kB/s
dropped_iterations.............: 123 1.983368/s
http_req_blocked...............: avg=23.83µs min=213ns med=799ns max=113.17ms p(90)=1.41µs p(95)=1.59µs
http_req_connecting............: avg=1.42µs min=0s med=0s max=6.53ms p(90)=0s p(95)=0s
http_req_duration..............: avg=69.21ms min=6.41ms med=54.17ms max=382.34ms p(90)=142.86ms p(95)=166.33ms
{ expected_response:true }...: avg=69.21ms min=6.41ms med=54.17ms max=382.34ms p(90)=142.86ms p(95)=166.33ms
http_req_failed................: 0.00% 0 out of 39678
http_req_receiving.............: avg=491.01µs min=23.44µs med=282.51µs max=20.46ms p(90)=1.01ms p(95)=1.6ms
http_req_sending...............: avg=106.95µs min=17.61µs med=85.46µs max=20.9ms p(90)=155.94µs p(95)=189.16µs
http_req_tls_handshaking.......: avg=18.91µs min=0s med=0s max=34.33ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=68.62ms min=6.23ms med=53.56ms max=381.34ms p(90)=142.08ms p(95)=165.56ms
http_reqs......................: 39678 639.805458/s
iteration_duration.............: avg=3.56s min=1s med=3.68s max=5.11s p(90)=4.22s p(95)=4.38s
iterations.....................: 778 12.545205/s
vus............................: 3 min=3 max=50
vus_max........................: 50 min=50 max=50
FastAPI scenario 2 #
Iteration creation rate = 2/s
checks.........................: 100.00% 82414 out of 82414
data_received..................: 164 MB 1.8 MB/s
data_sent......................: 6.1 MB 68 kB/s
dropped_iterations.............: 64 0.711058/s
http_req_blocked...............: avg=13.71µs min=208ns med=783ns max=143.23ms p(90)=1.39µs p(95)=1.56µs
http_req_connecting............: avg=1.28µs min=0s med=0s max=25.89ms p(90)=0s p(95)=0s
http_req_duration..............: avg=43.46ms min=3.99ms med=24.29ms max=315.4ms p(90)=108.49ms p(95)=129.33ms
{ expected_response:true }...: avg=43.46ms min=3.99ms med=24.29ms max=315.4ms p(90)=108.49ms p(95)=129.33ms
http_req_failed................: 0.00% 0 out of 82414
http_req_receiving.............: avg=205.46µs min=16.8µs med=103.34µs max=23.42ms p(90)=394.08µs p(95)=591.95µs
http_req_sending...............: avg=94.88µs min=17.56µs med=78.81µs max=14.63ms p(90)=143.76µs p(95)=171.26µs
http_req_tls_handshaking.......: avg=9.75µs min=0s med=0s max=29.89ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=43.16ms min=23.62µs med=23.97ms max=315.14ms p(90)=108.17ms p(95)=129.04ms
http_reqs......................: 82414 915.642582/s
iteration_duration.............: avg=1m5s min=44.88s med=1m10s max=1m14s p(90)=1m13s p(95)=1m13s
iterations.....................: 36 0.39997/s
vus............................: 21 min=2 max=50
vus_max........................: 50 min=50 max=50
NestJS #
NestJS scenario 1 #
Iteration creation rate = 20/s
checks.........................: 100.00% 50643 out of 50643
data_received..................: 857 MB 14 MB/s
data_sent......................: 4.7 MB 76 kB/s
dropped_iterations.............: 208 3.386691/s
http_req_blocked...............: avg=18.93µs min=174ns med=712ns max=77.19ms p(90)=1.29µs p(95)=1.48µs
http_req_connecting............: avg=964ns min=0s med=0s max=5.11ms p(90)=0s p(95)=0s
http_req_duration..............: avg=55.57ms min=3.38ms med=51.45ms max=156.06ms p(90)=101.84ms p(95)=106.83ms
{ expected_response:true }...: avg=55.57ms min=3.38ms med=51.45ms max=156.06ms p(90)=101.84ms p(95)=106.83ms
http_req_failed................: 0.00% 0 out of 50643
http_req_receiving.............: avg=393.14µs min=18.48µs med=253.43µs max=30ms p(90)=610.66µs p(95)=950.88µs
http_req_sending...............: avg=106.23µs min=22.01µs med=78.55µs max=20.42ms p(90)=148.81µs p(95)=187.14µs
http_req_tls_handshaking.......: avg=16.1µs min=0s med=0s max=34.53ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=55.07ms min=3.2ms med=50.96ms max=155.49ms p(90)=101.27ms p(95)=106.29ms
http_reqs......................: 50643 824.577783/s
iteration_duration.............: avg=2.88s min=993.46ms med=2.92s max=3.99s p(90)=3.28s p(95)=3.41s
iterations.....................: 993 16.168192/s
vus............................: 24 min=20 max=50
vus_max........................: 50 min=50 max=50
NestJS scenario 2 #
Iteration creation rate = 3/s
checks.........................: 100.00% 155200 out of 155200
data_received..................: 704 MB 8.5 MB/s
data_sent......................: 12 MB 150 kB/s
dropped_iterations.............: 80 0.966185/s
http_req_blocked...............: avg=6.88µs min=174ns med=660ns max=87.19ms p(90)=1.24µs p(95)=1.42µs
http_req_connecting............: avg=357ns min=0s med=0s max=7.72ms p(90)=0s p(95)=0s
http_req_duration..............: avg=21.55ms min=2.13ms med=18.15ms max=112.67ms p(90)=41.07ms p(95)=52.6ms
{ expected_response:true }...: avg=21.55ms min=2.13ms med=18.15ms max=112.67ms p(90)=41.07ms p(95)=52.6ms
http_req_failed................: 0.00% 0 out of 155200
http_req_receiving.............: avg=377.08µs min=14.17µs med=144.7µs max=45.51ms p(90)=704.67µs p(95)=1.31ms
http_req_sending...............: avg=92.1µs min=13.27µs med=68.38µs max=26.86ms p(90)=133.57µs p(95)=167.61µs
http_req_tls_handshaking.......: avg=5.04µs min=0s med=0s max=36.97ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=21.08ms min=0s med=17.7ms max=112.22ms p(90)=40.34ms p(95)=51.94ms
http_reqs......................: 155200 1874.398124/s
iteration_duration.............: avg=33.81s min=20.37s med=35.26s max=40.81s p(90)=39.62s p(95)=40.18s
iterations.....................: 100 1.207731/s
vus............................: 9 min=3 max=50
vus_max........................: 50 min=50 max=50
Spring Boot #
Spring Boot scenario 1 #
Iteration creation rate = 40/s
checks.........................: 100.00% 115209 out of 115209
data_received..................: 2.2 GB 36 MB/s
data_sent......................: 9.8 MB 162 kB/s
dropped_iterations.............: 142 2.337943/s
http_req_blocked...............: avg=9.76µs min=150ns med=495ns max=79.87ms p(90)=888ns p(95)=1.1µs
http_req_connecting............: avg=744ns min=0s med=0s max=8.88ms p(90)=0s p(95)=0s
http_req_duration..............: avg=23.5ms min=2.85ms med=21.95ms max=146.98ms p(90)=36.25ms p(95)=42.4ms
{ expected_response:true }...: avg=23.5ms min=2.85ms med=21.95ms max=146.98ms p(90)=36.25ms p(95)=42.4ms
http_req_failed................: 0.00% 0 out of 115209
http_req_receiving.............: avg=2.26ms min=18.74µs med=1ms max=82.11ms p(90)=5.64ms p(95)=8.68ms
http_req_sending...............: avg=147.6µs min=13.42µs med=55.61µs max=48.16ms p(90)=138.64µs p(95)=212.34µs
http_req_tls_handshaking.......: avg=7.73µs min=0s med=0s max=32.66ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=21.09ms min=0s med=19.81ms max=143.7ms p(90)=32.3ms p(95)=37.67ms
http_reqs......................: 115209 1896.845564/s
iteration_duration.............: avg=1.25s min=597.55ms med=1.26s max=1.6s p(90)=1.37s p(95)=1.4s
iterations.....................: 2259 37.19305/s
vus............................: 48 min=27 max=50
vus_max........................: 50 min=50 max=50
Spring Boot scenario 2 #
Iteration creation rate = 10/s
checks.........................: 100.00% 232800 out of 232800
data_received..................: 1.0 GB 14 MB/s
data_sent......................: 20 MB 270 kB/s
dropped_iterations.............: 450 5.968885/s
http_req_blocked...............: avg=5.53µs min=162ns med=501ns max=85.2ms p(90)=989ns p(95)=1.17µs
http_req_connecting............: avg=242ns min=0s med=0s max=6.7ms p(90)=0s p(95)=0s
http_req_duration..............: avg=14.96ms min=1.9ms med=13.28ms max=156.15ms p(90)=25.17ms p(95)=30.3ms
{ expected_response:true }...: avg=14.96ms min=1.9ms med=13.28ms max=156.15ms p(90)=25.17ms p(95)=30.3ms
http_req_failed................: 0.00% 0 out of 232800
http_req_receiving.............: avg=2.41ms min=17.6µs med=1.38ms max=71.34ms p(90)=5.57ms p(95)=8.28ms
http_req_sending...............: avg=92.57µs min=10.47µs med=55.14µs max=42.4ms p(90)=116.58µs p(95)=158.84µs
http_req_tls_handshaking.......: avg=4.04µs min=0s med=0s max=40.3ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=12.45ms min=0s med=11.04ms max=155.41ms p(90)=20.83ms p(95)=25.16ms
http_reqs......................: 232800 3087.903222/s
iteration_duration.............: avg=23.57s min=20.06s med=24.16s max=25.43s p(90)=24.79s p(95)=24.94s
iterations.....................: 150 1.989628/s
vus............................: 12 min=10 max=50
vus_max........................: 50 min=50 max=50
ASP.NET Core #
ASP.NET Core scenario 1 #
Iteration creation rate = 30/s
checks.........................: 100.00% 60537 out of 60537
data_received..................: 1.4 GB 22 MB/s
data_sent......................: 5.4 MB 88 kB/s
dropped_iterations.............: 614 10.010036/s
http_req_blocked...............: avg=18.21µs min=164ns med=643ns max=119.65ms p(90)=1.2µs p(95)=1.39µs
http_req_connecting............: avg=1.19µs min=0s med=0s max=7.21ms p(90)=0s p(95)=0s
http_req_duration..............: avg=47.41ms min=3.21ms med=47.19ms max=150.24ms p(90)=64.58ms p(95)=70.42ms
{ expected_response:true }...: avg=47.41ms min=3.21ms med=47.19ms max=150.24ms p(90)=64.58ms p(95)=70.42ms
http_req_failed................: 0.00% 0 out of 60537
http_req_receiving.............: avg=1.27ms min=21.28µs med=577.04µs max=53.67ms p(90)=2.93ms p(95)=4.89ms
http_req_sending...............: avg=115.28µs min=14.99µs med=72.14µs max=30.87ms p(90)=151.69µs p(95)=216.28µs
http_req_tls_handshaking.......: avg=14.34µs min=0s med=0s max=52.71ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=46.02ms min=2.92ms med=46.04ms max=148.92ms p(90)=62.52ms p(95)=67.86ms
http_reqs......................: 60537 986.934156/s
iteration_duration.............: avg=2.48s min=1s med=2.51s max=2.79s p(90)=2.64s p(95)=2.68s
iterations.....................: 1187 19.35165/s
vus............................: 24 min=24 max=50
vus_max........................: 50 min=50 max=50
ASP.NET Core scenario 2 #
Iteration creation rate = 10/s
checks.........................: 100.00% 155200 out of 155200
data_received..................: 930 MB 14 MB/s
data_sent......................: 14 MB 206 kB/s
dropped_iterations.............: 500 7.429243/s
http_req_blocked...............: avg=7.19µs min=170ns med=579ns max=70.57ms p(90)=1.14µs p(95)=1.32µs
http_req_connecting............: avg=367ns min=0s med=0s max=4.55ms p(90)=0s p(95)=0s
http_req_duration..............: avg=20.06ms min=1.85ms med=17.93ms max=227.21ms p(90)=35.09ms p(95)=41.47ms
{ expected_response:true }...: avg=20.06ms min=1.85ms med=17.93ms max=227.21ms p(90)=35.09ms p(95)=41.47ms
http_req_failed................: 0.00% 0 out of 155200
http_req_receiving.............: avg=1.3ms min=16.13µs med=566.94µs max=41.66ms p(90)=3.1ms p(95)=5.12ms
http_req_sending...............: avg=94.15µs min=11.56µs med=62.76µs max=35.14ms p(90)=130.16µs p(95)=171.55µs
http_req_tls_handshaking.......: avg=5.61µs min=0s med=0s max=52.65ms p(90)=0s p(95)=0s
http_req_waiting...............: avg=18.66ms min=0s med=16.5ms max=226.18ms p(90)=33.14ms p(95)=39.31ms
http_reqs......................: 155200 2306.036927/s
iteration_duration.............: avg=31.5s min=28.79s med=31.76s max=33.25s p(90)=32.83s p(95)=32.95s
iterations.....................: 100 1.485849/s
vus............................: 12 min=10 max=50
vus_max........................: 50 min=50 max=50
Conclusion #
Here are the final req/s results for each framework against PgSQL database.