nnestjs-drizzle-crud
Configuration

forRoot

Configure the database connection once in AppModule via DrizzleCrudModule.forRoot.

DrizzleCrudModule.forRoot(config) is called once in your AppModule. It owns the database connection, exposes it globally, and closes it on application shutdown (when the module built it from a connectionString).

Signature

DrizzleCrudModule.forRoot(config: DrizzleCrudConfig): DynamicModule

Options

FieldTypeDescription
dialect'postgresql' | 'mysql'Required. Database dialect.
connectionStringstringConnection string. The module builds the connection (PostgreSQL only).
dbDrizzle instanceAlternatively, pass a Drizzle instance you built yourself (any dialect).
schemaRecord<string, unknown>Drizzle schema, used when building from connectionString.
defaults.softDeletebooleanEnable soft delete for all entities (default true).
defaults.timestampsbooleanAuto-manage created_at / updated_at for all entities (default true).
defaults.pagination{ defaultLimit: number; maxLimit: number }Pagination defaults (default { 20, 100 }).
defaults.sortOrder'asc' | 'desc'Opt-in default sort. Entities without an explicit defaultSort fall back to ordering by their created_at column in this direction. Omit to leave findAll unsorted by default.
sql{ caseSensitive, useReturning, jsonSupport, enableFullTextSearch }Dialect tuning. useReturning defaults to true for PostgreSQL, false for MySQL.

Provide exactly one of connectionString or db. The module will throw if you pass neither, or both.

If your tables have no created_at / updated_at / deleted_at columns, set defaults: { softDelete: false, timestamps: false } — otherwise inserts will reference columns that don't exist.

PostgreSQL — let the module build the connection

app.module.ts
import { Module } from '@nestjs/common';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';

@Module({
  imports: [
    DrizzleCrudModule.forRoot({
      dialect: 'postgresql',
      connectionString: process.env.DATABASE_URL,
      schema,
      defaults: {
        softDelete: true,
        timestamps: true,
        pagination: { defaultLimit: 20, maxLimit: 100 },
      },
      sql: {
        caseSensitive: false,
        jsonSupport: true,
        enableFullTextSearch: true,
      },
    }),
  ],
})
export class AppModule {}

The module imports the postgres driver on your behalf and builds a Drizzle instance from your schema. The connection is closed automatically on app shutdown.

If you want full control over the connection — pool size, SSL, advanced mysql2 options, or you're on MySQL — pre-build the Drizzle instance and pass it as db:

app.module.ts (Postgres)
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';

const client = postgres(process.env.DATABASE_URL!);
const db = drizzle(client, { schema });

@Module({
  imports: [
    DrizzleCrudModule.forRoot({
      dialect: 'postgresql',
      db,
    }),
  ],
})
export class AppModule {}
app.module.ts (MySQL)
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';

const pool = mysql.createPool({
  uri: process.env.DATABASE_URL,
  connectionLimit: 10,
});
const db = drizzle(pool, { schema });

@Module({
  imports: [
    DrizzleCrudModule.forRoot({
      dialect: 'mysql',
      db,
    }),
  ],
})
export class AppModule {}

When you pass db, the module does not close the connection on shutdown — it's your responsibility. This makes it easy to share the same pool across other Drizzle consumers (custom services, raw queries, migrations).

sql tuning

OptionDefaultWhat it does
caseSensitivefalseWhen false, bare string filter values are compiled to lower(column) = lower(value) (case-insensitive exact match). When true, bare strings use plain equality (collation-dependent). Use the explicit { like } / { ilike } operators for pattern matching.
useReturningtrue (Postgres) / false (MySQL)Use RETURNING after INSERT to fetch the created row. MySQL doesn't support RETURNING — leave it off.
jsonSupporttrueEnables JSON column handling in filters and selects.
enableFullTextSearchfalseOpt-in for fullTextSearch(). Throws if called when false.

Defaults cheat sheet

defaults: {
  softDelete: true,                      // deletes set deleted_at = now()
  timestamps: true,                      // create/update stamp created_at/updated_at
  pagination: { defaultLimit: 20, maxLimit: 100 },
  sortOrder: 'desc',                     // opt-in: created_at fallback for findAll
},
sql: {
  caseSensitive: false,
  useReturning: dialect === 'postgresql',
  jsonSupport: true,
  enableFullTextSearch: false,
}

When to use forRootAsync

If your config comes from ConfigService (env validation, secrets, dynamic config), use forRootAsync instead of forRoot.

Next

On this page