Skip to content

nest-native/jobs

Repository files navigation

@nest-native/jobs

Background jobs for NestJS without Redis — a Drizzle-backed job queue (SQLite, Postgres & MySQL) with transactional enqueue, retries, delayed and unique jobs.

NPM Version NPM Downloads Package License Test Coverage Documentation

Note

v0.x — early but stable. The producer, claimer, handler discovery, and the three Drizzle stores are implemented and tested at 100% coverage. SQLite, Postgres, and MySQL are supported.

The problem it solves

Most NestJS apps grow a first background job long before they need a queueing system: send a welcome email after signup, generate a report, retry a flaky webhook. The official NestJS answer is @nestjs/bullmq — which means operating Redis for what is often a handful of jobs a minute. And because Redis is a second system, the classic dual-write bug appears on day one: the signup commits but the process crashes before queue.add() — the email is never sent. Or queue.add() succeeds and the transaction rolls back — a welcome email for a user that does not exist.

@nest-native/jobs stores jobs in the same Drizzle database your app already has:

  • Transactional enqueueenqueue() inserts the job row inside your business transaction (via @nestjs-cls/transactional). The job exists if and only if your writes committed.
  • Nest-native execution — declare a class with @JobHandler('email.welcome'), register it as a provider, and the claimer dispatches to it with full DI. Handlers are discovered at bootstrap; duplicate names throw at startup.
  • Retries, delays, priorities, unique jobs — jittered exponential backoff (or RetryableError's explicit delayMs), PermanentError to fail fast, runAt/delayMs scheduling, priority ordering, and uniqueKey dedup among active jobs.
  • Zero runtime dependencies — everything (Nest, Drizzle, your driver) is a peer you already installed.

Install

npm install @nest-native/jobs
# plus your driver (peer dependencies):
npm install drizzle-orm @nestjs-cls/transactional better-sqlite3   # or pg / mysql2

Entry points

Import Contents
@nest-native/jobs core engine — JobsService (enqueue), JobsClaimer + runWorkerLoop, @JobHandler + JobsHandlerExplorer, RetryableError/PermanentError, the JobStore seam, JobsModule
@nest-native/jobs/sqlite better-sqlite3 (synchronous) store + the jobs table definition
@nest-native/jobs/postgres node-postgres (async) store + table definition
@nest-native/jobs/mysql mysql2 (async) store + table definition
@nest-native/jobs/testing drainJobs + RecordingJobHandler for hermetic tests

How it fits together

  1. Add the dialect's jobs table definition to your Drizzle schema and generate a migration with drizzle-kit.
  2. Configure @nestjs-cls/transactional with the Drizzle adapter, then register JobsModule.forRoot({ drizzleInstanceToken, store }).
  3. Inject JobsService into your @Transactional() services and enqueue() alongside your business writes — the job commits atomically with them.
  4. Declare @JobHandler('job.name') classes as providers; the explorer builds the name → handler registry at bootstrap.
  5. Run JobsClaimer in a worker (runWorkerLoop) — it claims due jobs in batches (priority first, oldest due first, reclaiming stuck ones) and dispatches to your handlers. Delivery is at-least-once — make handlers idempotent or key side effects on ctx.jobId.

See the 00-showcase sample for a runnable end-to-end example on SQLite, and the documentation for the full guide.

Honest comparison

BullMQ (@nestjs/bullmq) pg-boss @nest-native/jobs
Backing store Redis (required) Postgres only the Drizzle DB you already run — SQLite, Postgres, or MySQL
NestJS integration official wrapper module none (framework-agnostic) native — module, DI, @JobHandler decorators
Enqueue in your DB transaction no (Redis is a second system) yes (raw SQL in your tx) yes — first-class, via @nestjs-cls/transactional
Delivery Redis push (blocking ops) polling + LISTEN/NOTIFY polling claimer
Throughput very high high right-sized — polling batches, fine for most apps' background work
Repeatable / cron jobs yes yes no (non-goal — use @nestjs/schedule)
Dashboards, rate limiting yes partial no
Runtime dependencies Redis server + client pg zero (peers you already have)

If you need tens of thousands of jobs per second, sandboxed processors, or a dashboard, use BullMQ — it is excellent at that. If you run Postgres without Nest, pg-boss is battle-tested. This library is for the large middle: NestJS + Drizzle apps that want reliable background jobs without operating another system.

Quality Gates

Every PR runs the full gate — build, typecheck, coverage with c8 enforced at 100% for statements, branches, functions, and lines, cognitive complexity enforcement (SonarJS threshold 15), tarball validation, sample version sync, and a supply-chain audit:

npm run ci

Two optional, local-only layers sit on top (neither is required to contribute, and forks work without Docker):

  • Full modenpm run infra:up && npm run test:full runs the gated MySQL round-trip spec against a disposable Docker container (compose.yaml); npm run infra:down cleans up.
  • Mutation testingnpm run test:mutation (incremental Stryker run; test:mutation:full re-tests everything). Scope with STRYKER_MUTATE, include the gated MySQL spec with STRYKER_WITH_INFRA=1. Never runs in CI.

Details — including the pre-PR ritual and agent instructions — in GUIDELINES_NEST_JOBS.md.

Non-goals (v0.1)

  • Cron / repeatable jobs@nestjs/schedule already does this well; combine it with enqueue() if you want scheduled work to flow through the queue.
  • Dashboards / UI, rate limiting, concurrency groups.
  • LISTEN/NOTIFY push — the claimer polls; pollIntervalMs is your latency knob.
  • Redis-class throughput — this is a polling claimer over your relational DB, by design.

Part of the nest-native family. Not affiliated with the NestJS core team. MIT licensed.

About

Background jobs for NestJS without Redis — Drizzle-backed (SQLite/Postgres/MySQL), transactional enqueue, decorator-first handlers

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages