Backend / 2026-03-16
API Framework Benchmark for Data-Intensive Services
This report compares six API frameworks under data-intensive service workloads using PostgreSQL/Aurora, StarRocks/Iceberg, and OpenSearch. The benchmark ran in Docker with 2 CPU and 512 MB per container.
Go, Python, Node.js, and Bun
PostgreSQL, StarRocks, OpenSearch
Fiber, Fastify, BlackSheep, Elysia
Select a backend framework for data-intensive APIs where database latency and error behavior dominate request performance.
Implemented equivalent services across six frameworks and ran mixed, stress, sustained, and isolated endpoint workloads in Docker.
Fiber, Fastify, BlackSheep, and Elysia were reliable; database optimization mattered far more than framework overhead.
- Go
- Python
- Node.js
- Bun
- Docker
- PostgreSQL
- StarRocks
- OpenSearch
Frameworks compared
- Fiber (Go)
- FastAPI (Python)
- Fastify (Node.js)
- Elysia (Bun)
- Hono (Bun)
- BlackSheep (Python)
Key findings
- Four frameworks achieved 0% errors across all scenarios: Fiber, Fastify, BlackSheep, and Elysia.
- Database behavior dominated framework overhead. A roughly 100x gap between fast OpenSearch lookups and slow PostgreSQL aggregations mattered far more than the web framework.
- BlackSheep had the highest sustained throughput at 43.4 req/s with 0% errors.
- Fastify was the most consistent under load and had the best p95 mixed-load behavior.
- Fiber had the lowest overhead and smallest container footprint.
- Elysia had the fastest raw overhead but showed stress errors under slow-query pressure.
- Hono on Bun was the weakest fit in this workload due to mixed and stress error rates.
Recommendation
For Python, BlackSheep with asyncpg and aiomysql is the strongest performance choice, while FastAPI remains reasonable if ecosystem fit matters more. For TypeScript, Fastify is the safest default. For maximum raw speed and tiny containers, Fiber is the performance-oriented option.
The highest-leverage work is database optimization: Redis caching, materialized views for PostgreSQL aggregations, response compression, strict pagination, and moving heavy aggregations to StarRocks where appropriate.
Datastore notes
- PostgreSQL wide aggregations over six-month ranges took 9 to 14 seconds across frameworks.
- StarRocks handled heavy aggregations around 78 to 98 ms, but paginated Iceberg connector queries were slow at 2 to 4 seconds p50.
- OpenSearch was fastest for lookups and aggregations, with framework choice having little impact.
Detailed methodology and results
Supporting methodology, figures, and tables are rendered here as native page content with the same visual system as the rest of this website.
Generated 2026-03-16 18:04:13 Test environment: Docker (2 CPU / 512MB per container) Databases: PostgreSQL (Aurora), StarRocks (Iceberg), OpenSearch (AWS)
How to Read This Report
Key Terms
Recommendation: It depends on a team
With proper best-practice implementations, four frameworks achieved 0% error rates across all scenarios: Fiber (Go) , Fastify (Node.js) , BlackSheep (Python) , and Elysia (Bun) . The performance differences between them are driven by the databases, not the frameworks all produce nearly identical p50 latencies (235 282ms mixed). The right choice depends on a team's language expertise and ecosystem needs:
Already know Python? BlackSheep (0% errors, highest sustained throughput at 43 req/s, mature async ecosystem with asyncpg/aiomysql)
Already know TypeScript? Fastify (0% errors, fastest isolated query speed for PG/OS, huge npm ecosystem)
Want maximum raw speed + tiny containers? Fiber (Go) (0% errors, fastest health endpoint at 554 req/s isolated, 10MB Docker image)
Want fastest raw overhead? Elysia (Bun) (140K req/s overhead, 0% mixed/sustained errors, but 4% stress errors)
1. Scenario Overview
| Framework | Overhead (no DB) | Mixed Workload (150 VUs) | Stress Test (500 VUs) | Sustained (80 VUs, 2 min) | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| req/s | p50 | req/s | err% | p50 | p95 | p99 | req/s | err% | p50 | p95 | req/s | err% | p50 | p95 | |
| Fiber (Go) | 90631.0 | 321us | 29.4 | 0.0% | 281.7ms | 8.80s | N/A | 34.3 | 0.0% | 982.9ms | 32.18s | 29.0 | 0.0% | 275.7ms | 11.07s |
| FastAPI (Python) | 26944.6 | 3.4ms | 5.9 | 9.7% | 245.4ms | 60.00s | N/A | 18.3 | 14.1% | 219.7ms | 60.00s | 7.5 | 12.0% | 269.4ms | 60.00s |
| Fastify (Node.js) | 58424.3 | 1.5ms | 23.9 | 0.0% | 235.4ms | 12.53s | N/A | 32.6 | 0.0% | 374.1ms | 35.37s | 30.4 | 0.0% | 376.9ms | 9.97s |
| Elysia (Bun) | 139886.2 | 430us | 26.9 | 0.0% | 266.4ms | 9.95s | N/A | 28.9 | 4.0% | 392.7ms | 28.51s | 31.3 | 0.0% | 403.5ms | 9.17s |
| Hono (Bun) | 102372.0 | 809us | 17.9 | 11.3% | 252.3ms | 22.29s | N/A | 41.0 | 24.6% | 892.2ms | 23.23s | 22.1 | 3.7% | 386.1ms | 17.75s |
| BlackSheep (Python) | 42680.8 | 2.1ms | 30.2 | 0.0% | 262.0ms | 11.01s | N/A | 40.1 | 0.0% | 390.5ms | 28.89s | 43.4 | 0.0% | 347.5ms | 9.57s |
2. Visual Comparison
Throughput by Scenario (req/s)
Error Rate by Scenario (%)
Latency p50 p95 Mixed Scenario
Latency p50 p95 Stress Scenario
Isolated: Per-Endpoint Throughput (req/s)
Isolated: Per-Endpoint p50 Latency (ms)
3. Isolated Endpoint Tests
| Endpoint | Fiber (Go) | FastAPI (Python) | Fastify (Node.js) | Elysia (Bun) | Hono (Bun) | BlackSheep (Python) |
|---|---|---|---|---|---|---|
| Health (no DB) | 224us p90: 491us | p95: 613us 553.9 req/s | 1.9ms p90: 5.0ms | p95: 6.4ms 532.3 req/s | 1.8ms p90: 4.4ms | p95: 5.9ms 534.3 req/s | 1.3ms p90: 3.0ms | p95: 4.1ms 537.5 req/s | 1.1ms p90: 3.0ms | p95: 3.9ms 540.2 req/s | 2.4ms p90: 6.0ms | p95: 7.8ms 521.0 req/s |
| PG: Single Row | 34.7ms p90: 106.6ms | p95: 113.9ms 291.3 req/s | 71.6ms p90: 148.7ms | p95: 157.5ms 206.4 req/s | 36.7ms p90: 115.1ms | p95: 122.6ms 281.4 req/s | 37.1ms p90: 117.1ms | p95: 124.0ms 253.9 req/s | 36.5ms p90: 113.3ms | p95: 121.5ms 281.4 req/s | 75.1ms p90: 157.1ms | p95: 166.7ms 198.2 req/s |
| PG: Paginated (20) | 38.4ms p90: 117.9ms | p95: 125.1ms 272.7 req/s | 73.3ms p90: 150.8ms | p95: 157.6ms 202.6 req/s | 37.0ms p90: 119.0ms | p95: 125.6ms 262.5 req/s | 38.0ms p90: 117.4ms | p95: 123.1ms 276.4 req/s | 38.4ms p90: 117.2ms | p95: 124.6ms 275.1 req/s | 77.5ms p90: 160.0ms | p95: 171.2ms 192.8 req/s |
| PG: Paginated (100) | 67.1ms p90: 168.6ms | p95: 194.3ms 204.2 req/s | 118.8ms p90: 212.0ms | p95: 246.6ms 151.4 req/s | 56.2ms p90: 141.1ms | p95: 157.6ms 227.1 req/s | 56.5ms p90: 143.6ms | p95: 165.9ms 224.2 req/s | 57.1ms p90: 148.5ms | p95: 171.5ms 221.3 req/s | 100.2ms p90: 187.4ms | p95: 204.8ms 166.5 req/s |
| PG: Agg (1 month) | 1.82s p90: 2.79s | p95: 3.04s 15.6 req/s | 1.71s p90: 2.62s | p95: 2.99s 15.8 req/s | 1.84s p90: 2.57s | p95: 2.85s 15.9 req/s | 1.84s p90: 2.72s | p95: 2.95s 15.7 req/s | 1.88s p90: 2.82s | p95: 3.07s 15.2 req/s | 1.50s p90: 2.37s | p95: 2.58s 18.2 req/s |
| PG: Agg (6 months) | 14.06s p90: 18.20s | p95: 18.59s 2.3 req/s | 9.15s p90: 21.36s | p95: 25.37s 0.9 req/s | 10.52s p90: 15.41s | p95: 16.45s 2.6 req/s | 10.29s p90: 15.58s | p95: 17.48s 2.7 req/s | 10.33s p90: 20.84s | p95: 21.61s 2.2 req/s 55.8% | 9.27s p90: 13.16s | p95: 14.12s 3.1 req/s |
| SR: Single Row | 213.8ms p90: 346.1ms | p95: 427.6ms 102.0 req/s | 73.7ms p90: 148.0ms | p95: 162.8ms 202.7 req/s | 92.2ms p90: 165.3ms | p95: 184.0ms 186.1 req/s | 157.6ms p90: 248.7ms | p95: 264.9ms 135.0 req/s | 91.1ms p90: 165.0ms | p95: 181.9ms 188.1 req/s | 75.7ms p90: 157.4ms | p95: 174.9ms 195.7 req/s |
| SR: Paginated (20) | 2.96s p90: 6.09s | p95: 7.31s 8.3 req/s | 2.51s p90: 5.13s | p95: 5.74s 10.0 req/s | 3.01s p90: 5.09s | p95: 5.68s 9.2 req/s | 3.79s p90: 5.58s | p95: 6.12s 7.5 req/s | 3.41s p90: 5.04s | p95: 6.11s 8.5 req/s | 2.15s p90: 4.79s | p95: 6.56s 11.0 req/s |
| SR: Agg (1 month) | 154.2ms p90: 266.6ms | p95: 293.5ms 132.5 req/s | 78.4ms p90: 159.2ms | p95: 196.6ms 193.5 req/s | 96.1ms p90: 166.3ms | p95: 184.9ms 184.6 req/s | 98.0ms p90: 171.5ms | p95: 193.4ms 183.6 req/s | 95.5ms p90: 166.6ms | p95: 189.4ms 184.5 req/s | 78.4ms p90: 153.1ms | p95: 174.9ms 195.7 req/s |
| OS: Doc Lookup | 59.7ms p90: 126.4ms | p95: 139.4ms 235.2 req/s | 44.3ms p90: 141.8ms | p95: 183.0ms 234.1 req/s | 38.9ms p90: 113.9ms | p95: 120.1ms 278.8 req/s | 40.0ms p90: 111.6ms | p95: 118.6ms 154.0 req/s | 39.4ms p90: 112.4ms | p95: 120.5ms 277.4 req/s | 44.5ms p90: 131.7ms | p95: 155.2ms 243.3 req/s |
| OS: Search (20) | 149.2ms p90: 255.4ms | p95: 284.9ms 138.1 req/s | 333.4ms p90: 577.8ms | p95: 650.7ms 72.6 req/s | 247.3ms p90: 578.4ms | p95: 793.9ms 84.0 req/s | 187.1ms p90: 516.0ms | p95: 738.6ms 40.6 req/s | 205.4ms p90: 635.2ms | p95: 858.2ms 59.2 req/s | 263.1ms p90: 604.2ms | p95: 726.8ms 82.2 req/s |
| OS: Search (100) | 636.6ms p90: 1.90s | p95: 2.97s 33.3 req/s | 2.36s p90: 4.02s | p95: 4.41s 12.8 req/s | 1.44s p90: 3.44s | p95: 4.36s 16.4 req/s | 1.79s p90: 3.61s | p95: 4.90s 12.3 req/s | 1.27s p90: 3.73s | p95: 5.08s 16.0 req/s | 2.10s p90: 4.06s | p95: 5.00s 13.4 req/s |
| OS: Aggregation | 62.3ms p90: 128.2ms | p95: 139.3ms 234.1 req/s | 42.2ms p90: 120.2ms | p95: 131.7ms 260.0 req/s | 42.2ms p90: 104.8ms | p95: 113.4ms 274.4 req/s | 41.7ms p90: 107.1ms | p95: 115.4ms 273.9 req/s | 41.6ms p90: 107.8ms | p95: 116.0ms 275.3 req/s | 48.2ms p90: 134.1ms | p95: 161.1ms 238.0 req/s |
4. Mixed Workload Per-Endpoint Breakdown
| Endpoint | Fiber (Go) | FastAPI (Python) | Fastify (Node.js) | Elysia (Bun) | Hono (Bun) | BlackSheep (Python) |
|---|---|---|---|---|---|---|
| Health (overhead) | 136us avg: 147us | p90: 214us | p95: 249us | 548us avg: 780us | p90: 1.3ms | p95: 1.4ms | 513us avg: 1.4ms | p90: 1.6ms | p95: 2.8ms | 357us avg: 1.4ms | p90: 3.1ms | p95: 5.3ms | 590us avg: 2.1ms | p90: 3.9ms | p95: 8.3ms | 570us avg: 1.9ms | p90: 2.9ms | p95: 10.5ms |
| PG: Single Row | 3.58s avg: 3.72s | p90: 7.40s | p95: 7.81s | 334.8ms avg: 17.88s | p90: 60.00s | p95: 60.00s | 4.11s avg: 4.92s | p90: 11.47s | p95: 12.03s | 4.46s avg: 4.30s | p90: 8.38s | p95: 8.95s | 3.86s avg: 7.60s | p90: 21.78s | p95: 22.84s | 1.38s avg: 2.50s | p90: 6.28s | p95: 7.62s |
| PG: Paginated (20) | 3.83s avg: 3.89s | p90: 7.56s | p95: 7.81s | 2.34s avg: 24.06s | p90: 60.00s | p95: 60.00s | 6.01s avg: 5.63s | p90: 11.72s | p95: 12.19s | 4.42s avg: 4.37s | p90: 8.54s | p95: 9.05s | 4.03s avg: 9.48s | p90: 23.09s | p95: 23.50s | 1.18s avg: 2.51s | p90: 6.14s | p95: 8.28s |
| PG: Paginated (100) | 3.86s avg: 3.88s | p90: 7.65s | p95: 7.99s | 363.1ms avg: 18.79s | p90: 60.00s | p95: 60.00s | 6.11s avg: 5.14s | p90: 11.40s | p95: 11.70s | 3.86s avg: 4.29s | p90: 8.69s | p95: 9.11s | 5.13s avg: 8.87s | p90: 23.03s | p95: 23.41s | 1.75s avg: 2.83s | p90: 7.62s | p95: 8.45s |
| PG: Agg (1 month) | 4.51s avg: 4.44s | p90: 8.08s | p95: 8.66s | 43.22s avg: 37.12s | p90: 60.00s | p95: 60.00s | 5.29s avg: 5.68s | p90: 12.23s | p95: 13.07s | 4.98s avg: 5.47s | p90: 9.90s | p95: 10.27s | 6.65s avg: 10.37s | p90: 23.36s | p95: 23.69s | 3.90s avg: 4.72s | p90: 9.34s | p95: 10.70s |
| PG: Agg (6 months) | 9.96s avg: 10.02s | p90: 13.90s | p95: 15.23s | 60.00s avg: 60.00s | p90: 60.00s | p95: 60.00s | 13.03s avg: 12.41s | p90: 19.01s | p95: 20.37s | 12.68s avg: 12.09s | p90: 16.48s | p95: 17.35s | 20.02s avg: 15.42s | p90: 23.27s | p95: 23.52s | 12.93s avg: 13.38s | p90: 19.35s | p95: 20.68s |
| SR: Single Row | 178.7ms avg: 203.6ms | p90: 307.9ms | p95: 339.3ms | 66.5ms avg: 102.9ms | p90: 177.7ms | p95: 258.9ms | 70.2ms avg: 95.2ms | p90: 154.9ms | p95: 196.9ms | 98.1ms avg: 135.0ms | p90: 207.3ms | p95: 259.7ms | 68.6ms avg: 92.5ms | p90: 149.4ms | p95: 157.6ms | 73.4ms avg: 100.9ms | p90: 153.2ms | p95: 173.2ms |
| SR: Paginated (20) | 2.02s avg: 2.11s | p90: 3.60s | p95: 3.79s | 2.10s avg: 2.21s | p90: 3.55s | p95: 3.84s | 1.93s avg: 1.92s | p90: 3.27s | p95: 3.42s | 2.04s avg: 2.15s | p90: 3.58s | p95: 3.74s | 1.88s avg: 1.89s | p90: 3.46s | p95: 3.56s | 2.05s avg: 2.11s | p90: 3.58s | p95: 3.93s |
| SR: Paginated (100) | 2.12s avg: 2.20s | p90: 3.52s | p95: 3.83s | 2.02s avg: 2.17s | p90: 3.68s | p95: 3.95s | 1.92s avg: 1.95s | p90: 3.34s | p95: 3.42s | 2.01s avg: 2.13s | p90: 3.83s | p95: 4.03s | 2.00s avg: 1.99s | p90: 3.39s | p95: 3.62s | 2.05s avg: 2.10s | p90: 3.72s | p95: 3.81s |
| SR: Agg (1 month) | 135.9ms avg: 171.1ms | p90: 271.6ms | p95: 320.6ms | 60.5ms avg: 99.4ms | p90: 188.0ms | p95: 279.5ms | 62.4ms avg: 82.1ms | p90: 139.7ms | p95: 148.1ms | 66.6ms avg: 129.2ms | p90: 241.9ms | p95: 446.9ms | 64.7ms avg: 82.6ms | p90: 141.5ms | p95: 149.6ms | 65.3ms avg: 86.4ms | p90: 141.5ms | p95: 156.5ms |
| SR: Agg (6 months) | 129.2ms avg: 174.7ms | p90: 265.4ms | p95: 295.1ms | 65.6ms avg: 80.1ms | p90: 133.2ms | p95: 147.9ms | 67.7ms avg: 86.2ms | p90: 144.5ms | p95: 154.3ms | 69.7ms avg: 106.8ms | p90: 157.7ms | p95: 252.3ms | 66.7ms avg: 83.1ms | p90: 131.7ms | p95: 150.7ms | 68.7ms avg: 92.8ms | p90: 144.7ms | p95: 205.5ms |
| OS: Doc Lookup | 34.4ms avg: 47.6ms | p90: 102.7ms | p95: 113.3ms | 36.4ms avg: 49.1ms | p90: 89.7ms | p95: 118.0ms | 36.9ms avg: 53.1ms | p90: 105.6ms | p95: 115.4ms | 39.6ms avg: 50.4ms | p90: 99.8ms | p95: 113.1ms | 39.9ms avg: 53.4ms | p90: 106.6ms | p95: 122.4ms | 39.5ms avg: 56.6ms | p90: 112.9ms | p95: 121.8ms |
| OS: Search (20) | 61.5ms avg: 89.6ms | p90: 155.2ms | p95: 186.6ms | 253.3ms avg: 248.5ms | p90: 315.9ms | p95: 326.6ms | 97.2ms avg: 118.6ms | p90: 211.7ms | p95: 252.8ms | 90.1ms avg: 120.8ms | p90: 223.3ms | p95: 249.1ms | 108.9ms avg: 131.2ms | p90: 248.3ms | p95: 275.5ms | 189.0ms avg: 191.8ms | p90: 285.3ms | p95: 299.8ms |
| OS: Search (100) | 155.5ms avg: 175.1ms | p90: 286.2ms | p95: 295.6ms | 418.5ms avg: 417.4ms | p90: 512.6ms | p95: 537.2ms | 248.4ms avg: 263.6ms | p90: 383.0ms | p95: 446.7ms | 282.8ms avg: 465.8ms | p90: 456.3ms | p95: 637.1ms | 288.1ms avg: 469.0ms | p90: 453.0ms | p95: 633.3ms | 384.1ms avg: 410.9ms | p90: 634.6ms | p95: 717.4ms |
| OS: Aggregation | 36.2ms avg: 52.2ms | p90: 104.1ms | p95: 114.9ms | 38.4ms avg: 401.1ms | p90: 120.4ms | p95: 4.12s | 37.9ms avg: 49.0ms | p90: 85.0ms | p95: 108.6ms | 40.5ms avg: 53.0ms | p90: 105.7ms | p95: 117.1ms | 40.0ms avg: 55.8ms | p90: 112.1ms | p95: 122.0ms | 42.6ms avg: 58.5ms | p90: 111.3ms | p95: 121.7ms |
5. Stress Test Per-Endpoint Breakdown
| Endpoint | Fiber (Go) | FastAPI (Python) | Fastify (Node.js) | Elysia (Bun) | Hono (Bun) | BlackSheep (Python) |
|---|---|---|---|---|---|---|
| Health (overhead) | 150us avg: 193us | p95: 289us | 510us avg: 3.7ms | p95: 6.5ms | 435us avg: 2.5ms | p95: 11.9ms | 274us avg: 1.3ms | p95: 4.4ms | 629us avg: 1.8ms | p95: 5.4ms | 455us avg: 1.7ms | p95: 8.3ms |
| PG: Single Row | 17.88s avg: 18.19s | p95: 34.49s | 5.17s avg: 27.89s | p95: 60.00s | 21.73s avg: 19.87s | p95: 38.72s | 13.77s avg: 16.04s | p95: 60.00s | 20.73s avg: 15.07s | p95: 23.80s | 14.81s avg: 14.80s | p95: 31.41s |
| PG: Paginated (20) | 17.32s avg: 17.53s | p95: 34.69s | 1.88s avg: 24.52s | p95: 60.00s | 20.96s avg: 18.67s | p95: 37.95s | 13.45s avg: 16.16s | p95: 60.00s | 11.95s avg: 14.19s | p95: 23.81s | 16.01s avg: 14.70s | p95: 31.54s |
| PG: Paginated (100) | 17.24s avg: 16.35s | p95: 33.09s | 8.81s avg: 26.81s | p95: 60.00s | 21.42s avg: 19.33s | p95: 38.34s | 13.93s avg: 16.02s | p95: 60.00s | 11.95s avg: 14.25s | p95: 23.57s | 17.87s avg: 15.19s | p95: 31.32s |
| PG: Agg (1 month) | 17.94s avg: 18.13s | p95: 34.53s | 60.00s avg: 38.36s | p95: 60.00s | 22.47s avg: 20.73s | p95: 39.60s | 16.41s avg: 17.01s | p95: 31.24s | 11.95s avg: 14.62s | p95: 23.79s | 17.44s avg: 16.84s | p95: 33.29s |
| PG: Agg (6 months) | 21.65s avg: 22.19s | p95: 40.12s | 60.00s avg: 51.84s | p95: 60.00s | 27.15s avg: 25.62s | p95: 43.19s | 20.26s avg: 24.75s | p95: 60.00s | 20.82s avg: 17.47s | p95: 23.85s | 23.91s avg: 23.58s | p95: 39.67s |
| SR: Single Row | 464.9ms avg: 1.21s | p95: 4.80s | 71.6ms avg: 104.0ms | p95: 219.3ms | 126.5ms avg: 207.4ms | p95: 640.8ms | 155.5ms avg: 292.2ms | p95: 822.3ms | 212.0ms avg: 793.1ms | p95: 2.99s | 95.9ms avg: 168.0ms | p95: 472.2ms |
| SR: Paginated (20) | 2.51s avg: 3.06s | p95: 6.94s | 1.92s avg: 1.95s | p95: 3.61s | 1.97s avg: 2.07s | p95: 3.76s | 2.17s avg: 2.29s | p95: 4.28s | 2.23s avg: 2.70s | p95: 5.67s | 2.15s avg: 2.47s | p95: 5.34s |
| SR: Paginated (100) | 2.66s avg: 2.91s | p95: 5.21s | 1.97s avg: 2.05s | p95: 3.79s | 2.01s avg: 2.10s | p95: 3.65s | 2.19s avg: 2.31s | p95: 4.23s | 2.30s avg: 2.80s | p95: 6.13s | 2.13s avg: 2.46s | p95: 5.43s |
| SR: Agg (1 month) | 288.6ms avg: 916.7ms | p95: 4.14s | 71.4ms avg: 102.0ms | p95: 235.0ms | 105.2ms avg: 212.5ms | p95: 825.7ms | 117.5ms avg: 254.3ms | p95: 821.1ms | 152.1ms avg: 744.8ms | p95: 3.14s | 81.8ms avg: 156.1ms | p95: 510.2ms |
| SR: Agg (6 months) | 297.8ms avg: 873.8ms | p95: 3.22s | 69.7ms avg: 92.0ms | p95: 155.4ms | 110.3ms avg: 211.1ms | p95: 861.7ms | 125.0ms avg: 260.9ms | p95: 834.7ms | 170.0ms avg: 811.2ms | p95: 3.34s | 95.3ms avg: 160.7ms | p95: 523.0ms |
| OS: Doc Lookup | 36.3ms avg: 50.2ms | p95: 114.2ms | 36.8ms avg: 53.3ms | p95: 124.9ms | 37.8ms avg: 51.5ms | p95: 117.9ms | 40.9ms avg: 56.6ms | p95: 124.0ms | 41.7ms avg: 55.6ms | p95: 118.2ms | 38.8ms avg: 55.9ms | p95: 123.4ms |
| OS: Search (20) | 84.0ms avg: 102.1ms | p95: 209.9ms | 230.4ms avg: 225.3ms | p95: 336.1ms | 104.3ms avg: 126.2ms | p95: 279.5ms | 94.8ms avg: 613.2ms | p95: 297.9ms | 173.9ms avg: 316.1ms | p95: 399.2ms | 175.6ms avg: 178.1ms | p95: 301.7ms |
| OS: Search (100) | 172.5ms avg: 183.3ms | p95: 315.3ms | 394.1ms avg: 397.3ms | p95: 598.8ms | 309.6ms avg: 350.3ms | p95: 694.8ms | 326.2ms avg: 451.7ms | p95: 553.4ms | 420.9ms avg: 604.0ms | p95: 1.27s | 362.1ms avg: 397.8ms | p95: 807.2ms |
| OS: Aggregation | 37.5ms avg: 51.9ms | p95: 118.2ms | 38.2ms avg: 56.0ms | p95: 125.1ms | 39.0ms avg: 51.5ms | p95: 120.5ms | 42.8ms avg: 59.6ms | p95: 128.8ms | 42.7ms avg: 54.5ms | p95: 120.1ms | 41.9ms avg: 58.4ms | p95: 123.7ms |
6. Key Findings Recommendations
- Four frameworks achieved 0% errors across all scenarios. Fiber (Go), Fastify (Node.js), BlackSheep (Python), and Elysia (Bun) all handled mixed, stress, and sustained workloads with zero failures. This is a materially different result from the initial tests; fixed implementation issues such as missing SSL, wrong query parameter parsing, and StarRocks LIMIT syntax were responsible for most of the earlier "framework" errors.
- The database is the bottleneck, not the framework. Under real workload, all 6 frameworks produce nearly identical p50 latencies (235 282ms mixed). The 100x difference between a 39ms OpenSearch lookup and a 14s PostgreSQL aggregation dwarfs any framework overhead. Optimizing database queries (materialized views, caching, indexing) will deliver far more impact than switching frameworks.
- BlackSheep (Python) is the surprise performer. With proper async drivers (asyncpg + aiomysql), BlackSheep delivered the highest sustained throughput (43.4 req/s) and 0% errors everywhere . Its earlier 69% error rate was entirely due to a query-parameter handling issue, not the framework itself.
- Fastify (Node.js) is the most consistent under load. 0% errors in all scenarios, fastest isolated PG lookups (281 req/s, 37ms p50), and the best p95 latency under mixed load (12.5s vs 28 60s for others). If a team knows TypeScript, this is the safest choice.
- Fiber (Go) has the lowest per-request overhead (225us p50 health, vs 1 2ms for others) and the fastest PG row lookups (291 req/s, 35ms p50). The 10MB Docker image is 20x smaller than Python/Node containers. But the performance gap vs Fastify/BlackSheep is small once databases are involved.
- Elysia (Bun) has the fastest raw throughput at 140K req/s overhead 5x faster than FastAPI. Under real database load it performs well (0% mixed/sustained errors), but shows 4% errors under extreme stress (500 VUs). Bun's single-threaded model struggles when many slow queries (PG agg wide) block simultaneously.
- Hono+Bun is the weakest contender. Despite 102K overhead throughput, it shows 11% mixed errors and 25% stress errors the worst among the six. Its single-threaded model combined with the pg/mysql2 drivers creates head-of-line blocking on slow queries. It also has a 56% error rate on PG Agg Wide isolated tests (the slowest query type).
- FastAPI (Python) is reliable but slow under pressure. 0% errors on isolated tests but 10 14% on load scenarios because asyncpg waits for slow queries up to the 60s timeout rather than failing fast. The p95 hitting exactly 60.00s confirms this. With lower timeout settings or query optimization, this would improve significantly.
- PostgreSQL aggregations need optimization. PG Agg Wide (6-month range) takes 9 14 seconds across ALL frameworks. This is a database issue: consider materialized views, pre-computed rollup tables, or moving heavy aggregations to StarRocks which handles them in 78 98ms.
- StarRocks paginated queries are universally slow (2 4s p50 across all frameworks). This is the StarRocks Iceberg connector overhead, not the framework. Consider caching frequent pagination results in Redis.
- Large responses cost 2 5x more. PG Paginated 100 rows (56 119ms) is 1.5 2x slower than 20 rows (37 77ms). OS Search 100 (1.3 2.4s) is 5 10x slower than 20 results (150 333ms). Implement strict pagination limits and consider response compression (gzip) for production.
- OpenSearch is consistently the fastest data source for lookups (39 60ms) and aggregations (42 62ms) across all frameworks. The framework choice has almost zero impact on OpenSearch performance.
7. Final Verdict
| If team knows Python: | BlackSheep with asyncpg + aiomysql. Zero errors, highest sustained throughput, same async drivers as FastAPI but with lower overhead. FastAPI is also excellent if you prefer its ecosystem (Pydantic, OpenAPI docs, middleware). |
|---|---|
| If team knows TypeScript: | Fastify with pg + mysql2 pools. Zero errors, most consistent p95 latency, fastest OpenSearch and PG queries in isolation. Massive npm ecosystem. Single-process scales with containers. |
| If performance is priority: | Fiber (Go) . Lowest per-request overhead, fastest PG lookups, 10MB container image, native multi-core via goroutines. Requires learning Go, but the language is simple and the ecosystem for APIs is mature. |
| Regardless of framework: | Invest in database optimization . Add Redis caching for hot queries, materialized views for PG aggregations, response compression, and strict pagination limits. These will deliver 10 100x more impact than any framework choice. |