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. The conventional wisdom that “ORMs are slow, query builders are fast” doesn’t hold when the ORM is designed for performance 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, run it, prove me wrong. No database needed, finishes in seconds:

github.com/rogerpadilla/ts-orm-benchmark