Head to head
Seven frameworks. Ten weighted criteria. Real benchmarks. Zero cherry-picking.
GET /json · 20k req · 100 concurrent
Live from benchmarks.json — regenerated by GitHub Actions on every push to main. Same runner, same load, no cherry-picking.
Auth + validation + DB read · Yatta vs Hono + Drizzle · measured 2026-10-06
Raw /json speed is one thing. Real APIs do auth checks, validate input, and hit the database. We benchmarked the identical route on both stacks: in-process Bearer token check, param validation, SQLite point-read, JSON response. Same 10,000 users, same operations — no network hops in either.
| Stack | req/s | p50 | p95 | p99 |
|---|---|---|---|---|
| Yatta (built-in ORM) | 2,026 | 36.9ms | 130.4ms | 192.9ms |
| Hono + Drizzle | 1,716 | 45.5ms | 144.0ms | 200.9ms |
Honest result: on an identical real-world route, Yatta is ~1.18x the throughput of a well-assembled Hono + Drizzle single-process app. Not 7-12x — that old figure compared in-process Yatta against network-hop microservices (an architecture difference, not a framework one). This is the apples-to-apples test.
Methodology: GET /api/user/:id, 2k warmup + 20k requests at 100 concurrency, 3 runs each (fresh server + DB per run), median run reported. In-memory SQLite, 10k seeded users. Absolute req/s is capped by the test VM; the relative gap was consistent across all runs.
SQLite · Yatta ORM vs Drizzle · same database · measured 2026-10-06
Same SQLite file, same table, same 10,000 rows, same operations. The only variable is the ORM. Yatta ships a typed SQLite ORM with zero setup.
| Operation | Yatta ORM | Drizzle |
|---|---|---|
| Indexed point read | 0.009ms | 0.043ms |
| Filtered list (100) | 0.071ms | 0.162ms |
| Insert + return | 0.188ms | 0.801ms |
| Transaction (3 ops) | 0.240ms | 0.667ms |
Methodology: one shared SQLite file (bun:sqlite), users table with 10k rows, identical PRAGMAs for both ORMs. 500 warmup + 5,000 timed iterations per operation, 3 full runs; reported = median of per-run medians. Lower is better.
Auth + users + posts + DB + validation + tests + deploy · estimates
Estimated hours for one developer to ship a complete app. These are estimates based on the number of packages to configure — not measured stopwatch times.
Shorter bar = faster to ship. Yatta wins because auth, DB, validation, and jobs are built in — no assembly required.
What ships in the box
| Feature | Yatta | NestJS | Fastif | Hono | Adonis | Elysia | Expres | Koa |
|---|---|---|---|---|---|---|---|---|
| Auth (sessions/JWT) | ● | ○ | ○ | ○ | ● | ○ | ○ | ○ |
| Database ORM | ● | ○ | ○ | ○ | ● | ○ | ○ | ○ |
| Realtime (WS/SSE) | ● | ○ | ○ | ○ | ● | ○ | ○ | ○ |
| Job queue | ● | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| Cache | ● | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| File storage | ● | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| ● | ○ | ○ | ○ | ● | ○ | ○ | ○ | |
| Rate limiting | ● | ○ | ● | ○ | ● | ○ | ○ | ○ |
| Validation | ● | ● | ● | ● | ● | ● | ○ | ○ |
| Observability | ● | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
Yatta ships these ten capabilities through its core runtime. Competing frameworks generally compose them through additional official or community packages (like @nestjs/* or @adonisjs/*) — each with its own config, version drift, and docs to manage.
RSS under load · measured 2026-10-06
Real RSS measurements — each framework’s /json server in its own OS process, 10k requests at 50 concurrency, RSS read from the OS.
Methodology: each framework's /json server in its own OS process, 10,000 requests at 50 concurrency, RSS read from the OS. Two rounds averaged. Lower is better.
10 criteria · published weights
Scores are editorial (1–10 per criterion). Weights: Performance 15%, Developer experience 15%, Architecture 15%, Ecosystem 15%, TypeScript 10%, Database / ORM 10%, Security 5%, Testing 5%, Deployment 5%, Maturity 5%. Total = Σ(score × weight). Reproduce it: the weights, per-framework scores, and formula live in app/compare/page.tsx in this repo.
Scores are editorial (1–10 per criterion). Weights: Performance 15%, Developer experience 15%, Architecture 15%, Ecosystem 15%, TypeScript 10%, Database / ORM 10%, Security 5%, Testing 5%, Deployment 5%, Maturity 5%. Total = Σ(score × weight). Reproduce it: the weights, per-framework scores, and formula live in app/compare/page.tsx in this repo.
Scores are editorial (1–10 per criterion). Weights: Performance 15%, Developer experience 15%, Architecture 15%, Ecosystem 15%, TypeScript 10%, Database / ORM 10%, Security 5%, Testing 5%, Deployment 5%, Maturity 5%. Total = Σ(score × weight). Reproduce it: the weights, per-framework scores, and formula live in app/compare/page.tsx in this repo.
Worker runtimes · 4 workers · 20k tasks · measured 2026-10-06
Task dispatch throughput across worker runtimes. Same machine, same test methodology: 20,000 echo tasks across 4 workers, measuring throughput, p99 latency, memory, and IPC round-trip cost.
| Runtime | Throughput | p99 | Memory | Workers | IPC |
|---|---|---|---|---|---|
| Yatta Runtime | 85,746 ops/s | 10.51ms | 52.5 MB | 4 | 0.049ms |
| Bun Workers | 104,623 ops/s | 2.13ms | 64.6 MB | 4 | 0.086ms |
| Node worker_threads | 40,888 ops/s | 7.46ms | 143.9 MB | 4 | 0.154ms |
| Deno Workers | 22,248 ops/s | 10.88ms | 105.1 MB | 4 | 0.181ms |
Honest note: Bun's raw workers edge out Yatta on pure echo throughput because Yatta's runtime includes the task scheduler, module isolation, and observability overhead. Yatta wins on batteries included — scheduling, multi-tenancy, and monitoring that raw workers don't provide.
Methodology: 20,000 ping-pong tasks dispatched across 4 workers. Throughput = tasks/second. p99 = 99th percentile task latency. IPC = single round-trip postMessage cost. All measured on the same machine, same day.
The challenge
Pick any framework. Build: user signup/login, posts CRUD, SQLite, validation, tests, deploy to production.
Time yourself. Then build it in Yatta.
ESTIMATED IMPLEMENTATION EFFORT: ~4H.
The rest take 6-16. That gap is the batteries.