knex

A flexible, portable SQL query builder for Node.js supporting PostgreSQL, MySQL, CockroachDB, SQL Server, SQLite3, and Oracle.

Library
npm
v3.3.0
20,339 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
55 /100 Fair
Development Activity 12
Maintenance 32
Community 76
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
80 /100 Excellent
Architecture 85
Code Quality 88
Innovation 65
Learning Curve 80

Knex.js is a batteries-included SQL query builder for Node.js that provides a unified, promise-based API across PostgreSQL, MySQL, MariaDB, CockroachDB, SQL Server, SQLite3, and Oracle. Rather than hiding SQL behind an opinionated abstraction, it exposes a chainable builder that compiles directly to dialect-correct SQL, alongside a schema builder for migrations, a connection-pooling layer built on tarn, and both promise and callback interfaces for streaming and transactional workflows.

With over 20,000 GitHub stars and more than 5 million weekly npm downloads, Knex is one of the most widely deployed query builders in the Node.js ecosystem and serves as the SQL foundation underneath higher-level ORMs like Objection.js and MikroORM. Its CLI (knex migrate, knex seed) and dialect-specific compiler architecture make it a common choice for teams that want fine-grained control over generated SQL without writing raw query strings by hand.

What You Get

  • A chainable query builder covering selects, joins, subqueries, and raw SQL escape hatches
  • A schema builder and CLI-driven migration/seed system for versioned database changes
  • Built-in connection pooling (via tarn) and first-class transaction support
  • TypeScript typings with generic row typing for query results
  • Dialect adapters for PostgreSQL, MySQL, MariaDB, CockroachDB, MSSQL, SQLite3, and Oracle

Common Use Cases

  • Building a typed data-access layer for a Node.js API without adopting a full ORM
  • Powering higher-level ORMs (Objection.js, MikroORM) as the underlying SQL compilation engine
  • Managing versioned schema migrations and seed data across environments
  • Supporting multiple database backends from a single codebase

Under The Hood

Architecture

The core Client class (lib/client.js) extends EventEmitter and acts as the central coordination point, holding config, a Logger, a connection pool (via tarn’s KnexPool from lib/pool.js), and factory methods that wire together QueryBuilder/QueryCompiler and SchemaBuilder/SchemaCompiler/TableBuilder/TableCompiler/ColumnBuilder/ColumnCompiler pairs. Each dialect under lib/dialects/ (postgres, mysql, mysql2, mariadb, mssql, sqlite3, better-sqlite3, oracledb, cockroachdb, pgnative, redshift) subclasses Client and overrides the compiler classes to emit dialect-correct SQL, so the builder/compiler split cleanly separates what query is being built from how it is rendered as SQL text, a layered strategy-pattern architecture. Execution flows through lib/execution/runner.js and lib/execution/transaction.js, which wrap the pool-acquired connection and run the compiled SQL, with streaming handed off through the formatter layer. Migrations (lib/migrations/) and the CLI (bin/cli.js) sit as a separate concern layered on top of the same Client and QueryBuilder primitives, so changing the core Client contract would ripple through every dialect subclass and the migration runner.

Tech Stack

Knex is plain JavaScript (the large majority of the codebase) with a hand-written but extensive TypeScript declaration file rather than being TypeScript-authored; dialect drivers such as pg, mysql, mysql2, mariadb, tedious, sqlite3/better-sqlite3, and oracledb are peer/optional dependencies rather than bundled. Runtime dependencies are deliberately minimal: tarn for connection pooling, lodash for utilities, commander/getopts for the CLI, interpret/rechoir/escalade for loading user config and migration files, and colorette for terminal output. The build pipeline uses tsc for type declarations and Prettier/ESLint for linting, tests run under Mocha with nyc for coverage plus a secondary tape suite, and tsd/tstyche provide type-level testing. CI spins up real database containers via docker-compose for every supported dialect rather than relying only on mocks.

Code Quality

The test suite is extensive and multi-layered: unit tests, full integration tests against real databases per dialect, CLI tests driven by Jake, and type-level tests that assert the exported TypeScript types compile correctly, a level of rigor uncommon even in mature libraries. Error handling favors explicit, typed error classes over generic throws, and the codebase enforces ESLint and Prettier via Husky pre-commit hooks and lint-staged. Naming is consistent and descriptive, with mirrored Builder/Compiler pairs per concern. CI enforces linting, unit tests, real-database integration tests, and static analysis on every change, with coverage tracked via nyc and Codecov.

API Design Knex’s core design choice, one chainable builder API that compiles to dialect-correct SQL for seven different databases, lets application code stay portable across databases without hiding SQL semantics behind an ORM’s object model, a genuinely different trade-off from schema-first ORMs. The library requires almost no boilerplate to get started, and the same builder object works identically whether awaited as a promise, used as a subquery, or streamed. Its long-standing role as the SQL layer underneath other ORMs is evidence of a well-designed, embeddable query-compilation API, a battle-tested, pragmatic design more than a novel technical mechanism.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers