Part 5 · 1 chapters · ~8 min
TypeORM, Sequelize, Kysely and MikroORM
TypeORM's mixed Data Mapper and Active Record, the EntityManager and metadata storage, the synchronize footgun, Sequelize's older model and hooks, Kysely as a type-safe query builder that is not an ORM, MikroORM's identity map and unit of work done properly in TypeScript, and choosing with evidence.
9
Four more, compared
| TypeORM | Sequelize | Kysely | MikroORM | |
|---|---|---|---|---|
| kind | ORM (Data Mapper + Active Record) | ORM (Active Record) | query builder | ORM (Data Mapper) |
| schema | decorators on classes | model definitions | a TypeScript database interface (often generated) | decorators or defineEntity |
| identity map / unit of work | partial | no | no (by design) | yes, per request context |
| type safety of results | moderate | weak | strong | strong |
| watch out for | synchronize: true altering production schemas; lazy relations | hooks with side effects; ageing TypeScript support | you write every join yourself | flush semantics to learn |
code
// the TypeORM footgun: never in production
new DataSource({ type: 'postgres', synchronize: true }) // diffs entities and ALTERs live tables on startup
// MikroORM: unit of work with a request-scoped EntityManager
const em = orm.em.fork();
const acct = await em.findOneOrFail(Account, id);
acct.balanceKobo -= amt; // tracked
await em.flush(); // one UPDATE, in a transactionChoosing with evidence: write the three hardest queries in your domain (a report, a locking transfer, a nested read) in each candidate and read the SQL each produces. That afternoon decides better than any feature table.