Benchmark
Our open-source benchmark puts each ORM through a full PostgreSQL lifecycle: insert, read, update, read, nested read, delete, read. Here is the latest run.

Node.js v24.18.1, Apple M4 Pro, PostgreSQL 18.4, August 2026. µs per operation, median of 250 interleaved iterations. UQL 0.26.3, Prisma 7.9.1, TypeORM 1.1.0, MikroORM 7.1.11, Sequelize 6.37.8, Drizzle 0.45.2.
Results
Section titled “Results”Adds is what the ORM itself costs, everything on top of what the driver would have spent anyway.
| Entry | Adds µs | Total µs |
|---|---|---|
| UQL (Bun SQL) | +206 | 1,501 |
UQL (pg) |
+232 | 1,621 |
| Drizzle (Bun SQL) | +644 | 1,939 |
Drizzle (pg) |
+685 | 2,074 |
| TypeORM | +838 | 2,227 |
| Sequelize | +1,185 | 2,574 |
| Prisma | +1,345 | 2,734 |
| MikroORM | +2,236 | 3,625 |
The totals only span 2.4x, because everyone waits on the same database. Take that away and what the ORMs add spans 11x.
UQL adds the least, and the driver matters less next to that than you might expect: the same UQL code costs 206µs on Bun SQL and 232µs on pg, a 26µs gap, while moving to the next fastest ORM on the same driver costs 453µs.
The nested read spreads the field widest, since it is the only step that loads a relation: 50 parents with their children take UQL 346µs, Drizzle 535µs, and MikroORM 1,205µs. The interactive charts break down every step.
The floor
Section titled “The floor”Hand-written SQL with the rows mapped by hand: what an ORM has to earn its keep against. Bun SQL entries are measured against bun sql and the rest against raw pg, so a fast driver never gets counted as the ORM’s doing.
| Entry | Total µs |
|---|---|
| bun sql | 1,295 |
| raw pg | 1,389 |
Why UQL is fast
Section titled “Why UQL is fast”- Schema metadata is worked out once at startup, so nothing is looked up while a query runs.
- SQL is written straight into a string buffer, with no intermediate builder objects.
$populateloads a to-many relation with one batched query covering every parent, so the statement count follows the query’s shape rather than the result’s size.
Method
Section titled “Method”- Everyone defines the same
CompanyandUser, runs the same seven steps through its own idiomatic API, and gets one connection with no pooling. - Every step asserts on the rows it returns, so a step that silently does nothing fails instead of scoring well.
- Entries are interleaved and rotated, so none of them keeps a favourable position.
git clone https://github.com/rogerpadilla/ts-orm-benchmark.gitcd ts-orm-benchmarkbun install
DATABASE_URL=postgres:///postgres npm run benchSpeed is only one axis. For how the APIs and features line up, see the ORM Comparison.