
NestJS Knex Example: Step-by-Step Guide to Building Scalable SQL Application
Are you trying to use Knex.js with NestJS but feeling lost? You're not alone. While NestJS is packed with modern features, integrating it with SQL query builders like Knex requires a bit of setup. This beginner-friendly guide walks you through how to connect Knex with NestJS from scratch, covering configuration, migrations, query examples, real-world use cases and best practices. Whether you're using PostgreSQL, MySQL or SQLite, this comprehensive tutorial will help you build powerful and scalable SQL-based applications using Knex and NestJS.

Dev Orbit
August 2, 2025
Introduction to SQL with NestJS
In a backend ecosystem dominated by ORMs like TypeORM and Sequelize, it's easy to overlook the power of raw SQL and lightweight query builders. NestJS—a framework known for its structured architecture—works well with both.
But sometimes, developers want more control, faster performance and less abstraction. That’s where Knex.js comes in. Unlike heavy ORMs, Knex gives you the freedom to write raw, optimized SQL while still offering helpful utilities like migrations and query builders.
What is Knex.js?
Knex.js is a SQL query builder for Node.js that supports several relational databases like:
PostgreSQL
MySQL / MariaDB
SQLite3
MSSQL
It provides a clean, chainable syntax for writing SQL queries in JavaScript. While it’s not an ORM, Knex allows you to manage migrations, transactions and connections—making it ideal for projects that need SQL control without ORM overhead.
Benefits of Using Knex with NestJS
Here’s why developers often pair Knex with NestJS instead of an ORM:
Advantage | Explanation |
---|---|
Lightweight | No heavy abstractions or complex models |
Full SQL Control | Easily write raw queries when needed |
Better Performance | No hidden joins or auto-loading issues |
Database Flexibility | Easily switch between databases |
Scalable Architecture | Ideal for microservices and data-centric apps |
Setting Up a New NestJS Project
To get started, create a new NestJS project:
npm i -g @nestjs/cli
nest new nest-knex-app
cd nest-knex-app
Choose any package manager (npm/yarn) and clear out any boilerplate modules if necessary.
Installing Knex and Required Dependencies
Let’s install Knex and a SQL driver. For this example, we'll use PostgreSQL:
npm install knex pg
If you're using another DB:
MySQL:
npm install mysql2
SQLite:
npm install sqlite3
To enable migrations and CLI support, you can also install Knex globally:
npm install -g knex
Configuring Knex in a NestJS App
Create a knexfile.js
in your project root:
module.exports = {
development: {
client: 'pg',
connection: {
host: 'localhost',
user: 'your_user',
password: 'your_password',
database: 'your_db'
},
migrations: {
directory: './migrations'
}
}
};
Add this to your package.json
scripts:
"scripts": {
"migrate": "knex migrate:latest --knexfile knexfile.js",
"rollback": "knex migrate:rollback --knexfile knexfile.js"
}
Creating and Running Migrations
Create a migration to define your database schema:
knex migrate:make create_users_table --knexfile knexfile.js
CopyEdit
knex migrate:make create_users_table --knexfile knexfile.js
Edit the file in migrations/
:
exports.up = function(knex) {
return knex.schema.createTable('users', (table) => {
table.increments('id');
table.string('email').notNullable().unique();
table.string('name');
table.timestamps(true, true);
});
};
exports.down = function(knex) {
return knex.schema.dropTable('users');
};
Run the migration:
npm run migrate
Building a KnexService in NestJS
Create a new service that wraps Knex:
nest g service knex
In knex.service.ts
:
import { Injectable, OnModuleInit } from '@nestjs/common';
import knex from 'knex';
import * as config from '../../knexfile';
@Injectable()
export class KnexService implements OnModuleInit {
private db;
onModuleInit() {
this.db = knex(config.development);
}
get connection() {
return this.db;
}
}
Now you can inject KnexService
into any module and use .connection
to access the Knex instance.
Writing Basic SQL Queries Using Knex
Here’s how to use Knex in a controller or service:
const users = await this.knexService.connection('users')
.select('*')
.where({ email: '[email protected]' });
await this.knexService.connection('users').insert({
email: '[email protected]',
name: 'New User'
});
You can chain queries for sorting, filtering and pagination.
Knex with DTOs and Validation in NestJS
Use DTOs for type safety and validation:
export class CreateUserDto {
@IsEmail()
email: string;
@IsOptional()
@IsString()
name?: string;
}
Combine DTOs with your controller logic for cleaner and safer inputs.
Knex Query Examples by Use Case
Now let’s explore practical, real-world examples using Knex with NestJS:
1. Pagination
const users = await this.knexService.connection('users')
.select('*')
.limit(10)
.offset(20); // For page 3 (assuming 10 per page)
2. Search and Filtering
const results = await this.knexService.connection('users')
.where('name', 'ilike', `%john%`)
.andWhere('email', 'like', '%@gmail.com');
3. Joins
const posts = await this.knexService.connection('posts')
.join('users', 'users.id', 'posts.user_id')
.select('posts.*', 'users.name as authorName');
4. Transactions
await this.knexService.connection.transaction(async trx => {
await trx('users').insert({ email: '[email protected]' });
await trx('logs').insert({ action: 'User created' });
});
These examples show how Knex handles complex SQL tasks with clean, readable syntax.
Error Handling with Knex in NestJS
SQL can fail for various reasons—bad data, missing tables or constraint violations. NestJS makes it easy to manage these errors centrally.
Basic Try-Catch
try {
await this.knexService.connection('users').insert({ email: '[email protected]' });
} catch (error) {
throw new InternalServerErrorException(error.message);
}
Global Exception Filters
For consistent error handling, use NestJS filters:
@Catch(QueryFailedError)
export class DatabaseExceptionFilter implements ExceptionFilter {
catch(exception: QueryFailedError, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
response.status(500).json({ message: exception.message });
}
}
Testing Knex Queries in NestJS
To write tests, isolate logic in services and mock the Knex connection.
Mock KnexService
const mockKnexService = {
connection: jest.fn().mockReturnValue({
select: jest.fn().mockReturnValue([{ id: 1, email: '[email protected]' }]),
}),
};
Unit Test Example
it('should fetch users', async () => {
const users = await service.getUsers();
expect(users).toHaveLength(1);
});
Make sure you use test databases or mocking for safe and repeatable tests.
Switching Between Development and Production Databases
Use environment variables to control which Knex config gets loaded:
const config = require('./knexfile')[process.env.NODE_ENV || 'development'];
Maintain separate .env
files for:
Development
Testing
Production
This ensures proper isolation of data environments and reduces risk of destructive migrations.
Real-World Use Cases of Knex with NestJS
Here’s where this combo shines:
Use Case | Why Knex Works Well |
---|---|
SaaS platforms | Precise query control, better indexing |
Admin dashboards | Advanced filtering and joining |
Reporting engines | Optimized raw SQL queries |
Microservices | Lean, fast SQL operations without ORM bloat |
Knex is especially useful when performance and transparency are top priorities.
Common Pitfalls and Troubleshooting Tips
⚠️ Common Mistakes:
Forgetting to run migrations.
Misconfigured database credentials.
Query returning undefined due to missing
await
.
✅ Tips:
Always wrap DB calls in
try/catch
.Log Knex queries during development using
.debug()
.Use tools like PostgreSQL EXPLAIN to analyze slow queries.
FAQs About NestJS Knex Example
1. Is Knex.js an ORM?
No. Knex is a query builder—it helps write SQL with JS syntax but doesn’t manage models or relationships like an ORM.
2. Can I use Knex with TypeScript?
Absolutely. Knex has full TypeScript support and you can define your own types or interfaces for result sets.
3. Can I use raw SQL in Knex?
Yes, Knex supports raw queries:
await knex.raw('SELECT * FROM users WHERE id = ?', [1]);
4. Is Knex faster than TypeORM?
In many cases, yes. Knex is lightweight and doesn’t carry the overhead of models, decorators or auto-relations.
5. Can I switch to another database easily?
Yes, Knex supports multiple SQL dialects. You just need to change the client and connection config.
6. Should I use Knex for all NestJS projects?
Not necessarily. Use it when you need SQL-level control or want to avoid ORM abstraction for performance or complexity reasons.
Conclusion: Building Powerful SQL Apps with NestJS + Knex
If you're aiming to build structured, scalable SQL applications with complete control, the combination of NestJS + Knex is a game changer.
NestJS provides a clean, modular architecture ideal for enterprise applications, while Knex gives you the flexibility to write efficient, optimized SQL queries without the heaviness of an ORM.
Whether you're building a microservice, dashboard, reporting tool or a production-grade SaaS product—this stack enables rapid development, strict typing and full performance visibility.
Start small, follow the best practices and you’ll unlock the full potential of relational databases in a modern Node.js application.

Enjoyed this article?
Subscribe to our newsletter and never miss out on new articles and updates.
More from Dev Orbit

🚀 Mastering Python Automation in 2025: Deep Insights, Real-World Use Cases & Secure Best Practices
Streamline your workflows, eliminate manual overhead and secure your automation pipelines with Python — the most powerful tool in your 2025 toolkit.

10 JavaScript Quirks That Look Wrong (But Are Actually Right)
This article dives deep into ten surprising quirks of JavaScript that might confuse developers, especially those new to the language. From unexpected behavior with type coercion to peculiarities in operator precedence, we will clarify each aspect with real-world examples and practical implications. By understanding these quirks, developers can write cleaner and more efficient code, avoiding common pitfalls along the way.

Are AIs Becoming the New Clickbait?
In a world where online attention is gold, the battle for clicks has transformed dramatically. As artificial intelligence continues to evolve, questions arise about its influence on content creation and management. Are AIs just the modern-day clickbait artists, crafting headlines that lure us in without delivering genuine value? In this article, we delve into the fascinating relationship between AI and clickbait, exploring how advanced technologies like GPT-5 shape engagement strategies, redefine digital marketing, and what it means for consumers and content creators alike.

Improving API Performance Through Advanced Caching in a Microservices Architecture
Unlocking Faster API Responses and Lower Latency by Mastering Microservices Caching Strategies

AI Is Reshaping Jobs — and That Could Hit You Hard
As artificial intelligence continues to evolve, its impact on the job market is growing more profound each day. In this article, we will explore how AI technologies like GPT-5 are transforming various industries, the potential risks for workers, and actionable steps to navigate this changing landscape. From automation to the creation of new job roles, we will offer insights that every professional should be aware of to remain competitive in the era of AI.

Mastering Git Hooks for Automated Code Quality Checks and CI/CD Efficiency
Automate code quality and streamline your CI/CD pipelines with Git hooks. This step-by-step tutorial shows full-stack developers, DevOps engineers, and team leads how to implement automated checks at the source — before bad code ever hits your repositories.
Releted Blogs

MongoDB Insights in 2025: Unlock Powerful Data Analysis and Secure Your Database from Injection Attacks
MongoDB powers modern backend applications with flexibility and scalability, but growing data complexity demands better monitoring and security. MongoDB Insights tools provide critical visibility into query performance and help safeguard against injection attacks. This guide explores how to leverage these features for optimized, secure Python backends in 2025.

9 Powerful Reasons Why NestJS Beats Other Backend Frameworks in 2025
NestJS is revolutionizing how developers approach backend development in 2025. With built-in TypeScript support, modular architecture and first-class microservices integration, it's more than just a framework—it's a complete platform for building enterprise-grade, scalable applications. Discover why NestJS outshines Express, Django, Laravel and other backend giants in this in-depth comparison.

NestJS vs Express: Choosing the Right Backend Framework for Your Next Project
Are you torn between NestJS and Express for your next Node.js project? You're not alone. Both are powerful backend frameworks—but they serve very different purposes. This deep-dive comparison will help you decide which one fits your project's size, complexity and goals. Whether you're building a startup MVP or scaling a microservice architecture, we’ve covered every angle—performance, learning curve, architecture, scalability, testing and more.
Have a story to tell?
Join our community of writers and share your insights with the world.
Start Writing