Skip to content

In Search of the Fastest TypeScript ORM

Bar chart comparing SQL generation speed across TypeScript ORMs and query builders

I kept seeing “just use Drizzle, it’s lightweight” and “ORMs are slow, use a query builder” repeated everywhere. So I decided to actually measure it.

Pure SQL generation speed — no database, no network, no connection pool. Just the overhead your ORM adds to every single request.

7 entries. 8 query types. 3 runs averaged. Apple Silicon M4.


  • Environment: Node.js v24, Apple Silicon M4, 3 runs averaged.
  • Versions: Latest stable of every ORM/QB as of March 2026.
  • Fairness: Each ORM uses its most idiomatic API — QueryBuilder for TypeORM/MikroORM, which benefits them by skipping entity overhead.
  • What’s measured: Pure SQL string generation — no database, no I/O, no connection pool. This isolates ORM overhead only.
  • Why no Prisma? Prisma is not a pure TypeScript/JavaScript ORM — only its client is JS/TS. The query engine is a separate Rust binary that builds SQL, making it architecturally incomparable and not even testable this way.

Entryops/secvs winner
UQL606K 🥇
Knex407K0.67x
Sequelize202K0.33x
Kysely197K0.33x
MikroORM50K0.08x
TypeORM47K0.08x
Drizzle13K0.02x
Entryops/secvs winner
UQL1,817K 🥇
Kysely819K0.45x
Knex601K0.33x
TypeORM321K0.18x
Sequelize234K0.13x
MikroORM119K0.07x
Drizzle81K0.04x
Entryops/secvs winner
UQL693K 🥇
Knex349K0.50x
Sequelize334K0.48x
Kysely334K0.48x
TypeORM316K0.46x
MikroORM130K0.19x
Drizzle38K0.05x
Entryops/secvs winner
UQL3,642K 🥇
Sequelize1,349K0.37x
Kysely1,290K0.35x
Knex962K0.26x
TypeORM542K0.15x
Drizzle212K0.06x
MikroORM148K0.04x
Entryops/secvs winner
UQL3,994K 🥇
Sequelize3,143K0.79x
Kysely1,559K0.39x
Knex994K0.25x
TypeORM817K0.20x
MikroORM297K0.07x
Drizzle238K0.06x
Entryops/secvs winner
UQL1,200K 🥇
Knex480K0.40x
Kysely425K0.35x
Sequelize385K0.32x
TypeORM355K0.30x
Drizzle60K0.05x
MikroORM46K0.04x
Entryops/secvs winner
UQL644K 🥇
Kysely218K0.34x
Knex199K0.31x
TypeORM186K0.29x
Sequelize152K0.24x
Drizzle35K0.05x
MikroORM22K0.03x
Entryops/secvs winner
UQL1,489K 🥇
Sequelize407K0.27x
TypeORM364K0.24x
Knex284K0.19x
Kysely227K0.15x
Drizzle77K0.05x
MikroORM64K0.04x

📊 Interactive charts →


1. The “lightweight” query builder is the slowest thing in the benchmark.

Drizzle — marketed as lightweight — is slower than Sequelize (a full ORM from 2014) in every single category. The functional expression-tree approach creates more intermediate objects than Sequelize’s simple string concatenation.

2. Standalone query builders can’t beat a well-designed ORM.

Knex and Kysely have zero entity/relation overhead. They’re just SQL string builders. Yet UQL — a full ORM with entities, relations, and migrations — is faster than both in all 8 categories. This 4x-40x overhead advantage demonstrates that the conventional wisdom (“ORMs are slow”) doesn’t hold when the ORM is designed for performance with a Zero-Allocation architecture from day one.

3. MikroORM pays double.

MikroORM uses Knex internally as its SQL generator. So every query goes through two compilation layers: MikroORM → Knex → SQL string. The result? MikroORM averages 4-5x slower than Knex alone. That’s the cost of layering abstractions.


I got curious why the gap was so large, so I dug into the approach. Most ORMs figure out your schema at query time: “What table does User map to? What column is companyId? Is it nullable?” — they answer these questions on every single query.

UQL answers them once at startup. Field-to-column mappings, table names, relation paths — all pre-computed into lookup tables before the first query runs. At query time, generating SQL is just reading from a cache.

The other difference is allocation. When TypeORM builds a SELECT, it creates a QueryBuilder, then an expression tree, then walks the tree to produce SQL. UQL pushes SQL fragments directly into a string buffer — no intermediate objects, no garbage collection pressure.


Database latency is 1-50ms. ORM overhead is microseconds. So who cares?

You care at scale. If you’re running a moderately busy API — say 1,000 req/s:

  • UQL adds 1 CPU-second of ORM overhead
  • MikroORM adds 20 CPU-seconds — for the same queries

That’s 20x more CPU burned on generating SQL strings — pure waste before a single byte hits the network. In serverless (where you pay per ms), that’s your bill. In containers, that’s your horizontal scaling cost.


Full disclosure: I’m the author of UQL. That’s exactly why I built the benchmark as an independent repo anyone can audit and reproduce.

The full benchmark is open source — clone it, audit it, run it, share results. No database needed, finishes in seconds. See how UQL maintains its 4x-40x performance lead across every modern TypeScript environment.

Repo: ts-orm-benchmark