Introduction
Objection.js is an ORM for Node.js that embraces SQL rather than hiding it. Built on top of the Knex.js query builder, it adds model classes, relations, eager loading, and lifecycle hooks while keeping the full power of SQL accessible. Objection supports PostgreSQL, MySQL, MariaDB, SQLite, and MSSQL.
What Objection.js Does
- Defines models as JavaScript classes with typed relations (HasOne, HasMany, ManyToMany, BelongsToOne) and JSON Schema validation
- Provides eager loading via
withGraphFetchedandwithGraphJoinedfor loading related models in a single query or with joins - Supports graph inserts and upserts that persist an entire object graph with nested relations in one operation
- Exposes the underlying Knex.js query builder for raw SQL, subqueries, and complex joins when needed
- Handles transactions, lifecycle hooks (beforeInsert, afterFind, etc.), and model instance methods
Architecture Overview
Objection.js sits as a thin layer on top of Knex.js. Models extend the Model base class and declare a tableName and optional relationMappings. When a query is executed, Objection builds a Knex query, runs it against the database, and hydrates the results into model instances. Eager loading can use either separate queries per relation (withGraphFetched) or SQL joins (withGraphJoined). The query builder is chainable and returns model instances by default, but can return plain objects when needed. Schema validation uses JSON Schema via the ajv library, running before insert and update operations.
Self-Hosting & Configuration
- Install objection, knex, and a database driver (pg, mysql2, better-sqlite3) via npm
- Initialize Knex with a connection config and bind it to the Model base class with
Model.knex(knex) - Define model classes with
tableName,relationMappings, and optionallyjsonSchemafor validation - Use Knex migrations (
knex migrate:makeandknex migrate:latest) to manage database schema changes - Configure connection pooling in the Knex configuration for production environments
Key Features
- SQL-first philosophy: every query method maps to understandable SQL, with full access to raw expressions
- Graph operations (graphInsert, graphUpsert) that persist deeply nested object trees in a single call
- JSON Schema-based validation that runs automatically on insert and update
- Multiple eager loading strategies: separate queries for simplicity or joins for performance
- Full TypeScript support with typed models, queries, and relation definitions
Comparison with Similar Tools
- Sequelize — more abstracted ORM with its own query language; Objection stays closer to SQL and offers better TypeScript support
- TypeORM — decorator-based ORM inspired by Hibernate; Objection uses plain class definitions and is more SQL-transparent
- Prisma — schema-first with code generation; Objection is code-first and does not require a separate schema file
- Knex.js — the query builder Objection is built on; Objection adds models, relations, and validation on top
- MikroORM — Data Mapper pattern with Unit of Work; Objection uses Active Record-style queries with a SQL-first approach
FAQ
Q: Should I use withGraphFetched or withGraphJoined?
A: Use withGraphFetched (separate queries) for most cases as it avoids row duplication. Use withGraphJoined when you need to filter or order by a related model's columns.
Q: Does Objection.js support transactions?
A: Yes. Use Model.transaction() to wrap multiple queries in a database transaction with automatic commit and rollback.
Q: Can I use raw SQL with Objection.js?
A: Yes. Use raw() expressions in queries, or drop down to the Knex instance directly for fully custom SQL.
Q: Is Objection.js still maintained? A: Yes. Objection.js receives maintenance updates and has a stable API. The author considers it feature-complete, so releases focus on bug fixes and compatibility.