nestjs-drizzle-crud vs nestjs-paginate

nestjs-drizzle-crud vs nestjs-paginate compared. One is a CRUD layer for Drizzle ORM, the other a TypeORM helper for paginated, filtered lists.

nestjs-drizzle-crud vs nestjs-paginate is mostly a question of ORM and scope. nestjs-paginate is a pagination and filtering helper for TypeORM repositories and query builders: it reads a list request and returns one page with metadata and links. nestjs-drizzle-crud is a full CRUD layer for Drizzle ORM: lists, pagination and filtering are one part of it, next to create, update, delete, soft delete, upsert and bulk writes.

How this page was checked

Facts about nestjs-paginate come from its README and npm entry, checked on 2 November 2026 against version 16.0.1. Facts about nestjs-drizzle-crud come from the package source at version 3.6.0.

How do the two libraries differ at a glance?

nestjs-drizzle-crudnestjs-paginate
ORMDrizzle ORM (drizzle-orm from 0.28.0 up to, not including, 1.0.0)TypeORM (peer typeorm ^1.0.0 in 16.0.1, npm)
DatabasesPostgreSQL and MySQLPostgreSQL, CockroachDB, MySQL, MariaDB and SQLite appear in its JSONB support matrix
ScopeReads and writesReading paginated lists
Entry pointSqlBaseCrudService subclass per tablepaginate(query, repository, config) and the @Paginate() decorator
Offset paginationYes, { data, total, page, limit }Yes, { data, meta, links }, which the README says conforms to JSON:API
Cursor paginationYes, opaque cursor over any sortable columnsYes, on numeric and date columns (README)
Filter allowlistOptional; unset allows every columnRequired: operators are whitelisted per column in filterableColumns
Unknown filterAlways a 400Ignored by default, 400 with throwOnInvalidFilter: true
Boolean logicor, and, not groups as bracket keysA filter= expression with AND, OR, NOT and parentheses
To-many filterssome, none, every$any, $all, $none
SwaggerApiCrudList, ApiCrudQuery (optional @nestjs/swagger)@PaginatedSwaggerDocs, @ApiPaginationQuery, @ApiOkPaginatedResponse
LicenseMITMIT

Its npm page shows 16.0.1 published on 19 October 2026, and the GitHub repository had a push on 30 October 2026, as of November 2026. It is actively released.

What does nestjs-paginate do better?

Several things, each from its own README:

  • Secure filtering by default. A column cannot be filtered at all unless it is in filterableColumns, with its operators listed. In nestjs-drizzle-crud the allowlists are opt-in: with none set, any column can be filtered, sorted and selected. See Allowlists.
  • Response links. Each page carries links.first, previous, current, next and last, plus meta.totalPages. findAll returns total, page and limit and leaves link building to you.
  • A text filter language. filter=(color=$eq:black OR color=$eq:white) AND NOT name=$eq:Leche reads like a sentence and has a complexity cap (100 nodes by default).
  • JSONB paths, virtual columns and polymorphic (~) columns for sorting, searching and filtering.
  • More databases through TypeORM, including SQLite.
  • It works with your existing TypeORM repositories, so there is nothing to migrate if you are on TypeORM.

What does nestjs-drizzle-crud do that nestjs-paginate does not?

nestjs-paginate covers the read side only; its README documents no create, update or delete helpers. nestjs-drizzle-crud adds:

  • Writes: create, update, upsert, softDelete, restore, forceDelete, and mass versions that run in one transaction. See Bulk operations and Upsert.
  • Generated routes: createCrudController registers list, get, create, update, delete, soft delete, restore and trash routes. See CRUD controller factory.
  • Safety on writes: writableColumns, optimistic locking, tenant scopes and typed exceptions that map to 404, 409 and 400.
  • Relation counts and grouped counts with ?counts= and countBy. See Aggregates.
  • Drizzle ORM. If your schema is in Drizzle, nestjs-paginate cannot read it, because it works on TypeORM repositories and query builders.

How do the query strings compare?

The same list request in each, as each library documents it:

Intentnestjs-drizzle-crudnestjs-paginate
Page and sizepage=2&limit=5page=2&limit=5
SortsortBy=-colorsortBy=color:DESC
Exact matchcolor=whitefilter.color=white or filter.color=$eq:white
Operatorage[gte]=3filter.age=$gte:3
Rangeage[between]=4,6filter.age=$btw:4,6
Negationnot[id][in]=2,5,7filter.id=$not:$in:2,5,7
Nullseen_at[isNull]=truefilter.seenAt=$null
Starts withsummary[startsWith]=termfilter.summary=$sw:term
Search boxsearch=i (searches searchableColumns; a 400 without them)search=i (searches searchableColumns)
Columnsfields=id,name,colorselect=id,name,color
Soft-deleted rowswithDeleted=true (needs allowTrash)withDeleted=true (needs allowWithDeletedInQuery)
Cursorcursor= then cursor=<nextCursor>cursor=<value> with paginationType: PaginationType.CURSOR

See Parse query strings into filters for the nestjs-drizzle-crud side.

When should I choose nestjs-paginate?

Choose nestjs-paginate when:

  • your project uses TypeORM,
  • you only need paginated, filtered list endpoints and write the other routes yourself,
  • you want strict per-column operator whitelists by default, response links, or the filter= expression language, or
  • you need SQLite, JSONB path filters or virtual columns.

When should I choose nestjs-drizzle-crud?

Choose nestjs-drizzle-crud when:

  • your schema is in Drizzle ORM on PostgreSQL or MySQL,
  • you want reads and writes from one service, not only list pages,
  • you want generated routes, soft delete, upsert, bulk writes or tenant scopes without writing them, or
  • you want cursor pagination over text columns as well as numbers and dates.

Set the allowlists before you expose a list route, so a client can only touch the columns you name.

Common questions

Next steps

Last updated View change history

On this page