Sidequest: a background job queue that lives in your database
Redis-free background jobs for Node.js. Persist jobs in your existing Postgres, MySQL, SQLite, or MongoDB. A distributed, durable BullMQ alternative with a built-in dashboard.
At a glance
- What is it?
- Sidequest is a Node.js job processor that keeps its queue in the database you already run, PostgreSQL, MySQL, SQLite or MongoDB, so you can have durable distributed background jobs without standing up Redis. The parts worth understanding are the atomic claim that stops a job running twice and the execution model, where the engine forks and each job runs in a worker thread.
- Who is it for?
- Adopt Sidequest if you run Node.js services that already have a Postgres, MySQL, SQLite or MongoDB instance and you would rather not add and operate Redis just for a job queue, and if the built-in dashboard and CLI for migrations remove work from your plate. Do not adopt it if you need Bun support, since the README says it does not run on Bun yet, and treat SQLite as a development and testing choice rather than a production one, which the README states as well.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The pitch is one fewer service to run
Sidequest is a Redis-free background job processor for Node.js that persists jobs in the database you already run, whether PostgreSQL, MySQL, SQLite or MongoDB, and the README calls it a production-grade BullMQ and pg-boss alternative with a built-in web dashboard. The argument is not that Redis is a bad idea, it is that a queue is often the only reason a small team has to operate a second stateful service, and that a database is a stateful service the team already has, with backups, monitoring and a failover story. The at a glance section makes the promise concrete, with jobs described as durable and persisted in your database rather than in memory, and SQLite recommended for local development and tests. It also notes that the project does not run on Bun yet, and the installation section repeats that with a link to the issue tracking it, which is the kind of honesty that tells you the boundary of the support.
Exactly once is a locking problem, not a broker feature
The distribution line in the README is the one to read twice, because it is where the correctness claim lives. Sidequest runs across multiple nodes against one shared database, and jobs are claimed atomically with a `SELECT ... FOR UPDATE SKIP LOCKED` on Postgres and MySQL, so each job runs once. That is the entire mechanism, and it is worth understanding why it is enough. Several workers can be polling the same pending set at the same time, and the row lock plus the skip-locked clause lets exactly one of them take a given row while the others move on to the next available one without waiting. No broker is coordinating anything, because the database is doing the coordination with a primitive it already provides. The consequence for a reader is that the guarantee is tied to the database you chose, which is why the atomic claim is called out for Postgres and MySQL specifically, and why a backend with different locking semantics has to earn the same claim on its own.
A forked engine, worker threads for the jobs
The isolation model is stated in one line, that the engine runs in a forked child process while jobs execute in worker threads, and the features list adds that worker threads are how the processing stays non-blocking. Two consequences follow. Because the engine is a separate process, a job that takes the runtime down takes down its own process rather than the parent, and because the jobs themselves run in threads, a slow job does not block the others in the same process. The README also says that inline and no-fork execution modes are available, and it links to a section of the documentation on execution modes, which suggests this is a deliberate set of trade-offs rather than one fixed design. For a team debugging a stuck queue, that documentation page is the one to read before you start adding timeouts, because the answer to many questions is in which mode you are running.
What the built in feature set covers
The built-in list in the README is broad enough that the question becomes what is still yours to build. You get retries with exponential and fixed backoff, a snooze mechanism and explicit fail mechanisms, job uniqueness with flexible constraints so the same job is not enqueued twice, cron scheduling, and automatic recovery of stale jobs, which is the feature that stops a crashed worker from leaving a job stuck forever. The features list adds multiple queues with configurable workers and priorities, a responsive web dashboard for monitoring jobs and queues, a command line interface for database migrations and management, ESM and CommonJS support, and TypeScript job support by default if you are on Node.js 23.6.0 or later, where Node can run TypeScript natively. Monorepo architecture is listed too, which is a packaging decision rather than a feature, and it explains the install model.
The main package stays small and the backend is a separate install
The installation model is designed to keep the main package minimal, and the README says so directly, that to keep the application minimal the main package does not include the backend drivers, so you install only the driver you use. The core install is one package, and then there are four drivers, with the PostgreSQL one marked as recommended, the SQLite one marked as the default and not recommended for production, and MySQL and MongoDB available as well.
npm install sidequestnpm install @sidequest/postgres-backendUsing the code is three steps. You define a job class that extends `Job` and implements an async `run` method. You start Sidequest with a backend driver and a connection string, leaving the config empty to fall back to the default SQLite backend. And you enqueue work by building the job and calling `enqueue` on it. The dashboard listens on a port of its own, and the example prints the URL, so it is a separate local web interface rather than a route inside your app, which is worth knowing before you expose it.
The monorepo, its tooling and the numbered examples
The repository is a monorepo whose root package is private and named for the monorepo, with workspaces covering the packages, the backends and the examples, and the build and development commands driven by turbo, with the dev script running the packages concurrently and the clean scripts removing both the dist directories and the turbo caches. The test story is carefully separated. The default test run excludes the backend packages and the integration tests, the integration tests have their own scripts with a ten second timeout, there is a debug variant with no timeout, and the coverage script mirrors the same exclusions. Linting is eslint across the TypeScript and JavaScript sources, formatting is prettier, and the release process is automated with commitlint and release-please rather than by hand. The examples directory is the clearest teaching material, and it is numbered as a sequence, with a hello world, a recurring job, a snooze job, enqueuing a job from an API, a web scraping example and a dashboard base path example. There is also a script for spinning up a Postgres container for development.
Licence, release pace and what to check before you migrate
The project is licensed under LGPL-3.0-or-later, which is the interesting choice for a library that others embed in their services, and the README credits the two authors behind it. The release cadence is fast, with 1.16.4, 1.16.5 and 1.16.6 published in September and October 2026, and the last push on 2026-10-14, so the project is actively worked on rather than merely maintained. Before you migrate a production queue onto it, three things are worth checking against your own requirements. The runtime floor is Node.js 22.6.0 or later, and Bun is not supported yet. The once-only guarantee rests on the row locking behaviour of the backend you choose. And the built-in dashboard is a web interface into your job queue, so it needs the same access control and network placement decisions as any other admin surface in your estate. Beyond that, the documentation site, the FAQ and the migration guide from BullMQ are where the behavioural differences are spelled out.
Editorial conclusion
Adopt Sidequest if you run Node.js services that already have a Postgres, MySQL, SQLite or MongoDB instance and you would rather not add and operate Redis just for a job queue, and if the built-in dashboard and CLI for migrations remove work from your plate. Do not adopt it if you need Bun support, since the README says it does not run on Bun yet, and treat SQLite as a development and testing choice rather than a production one, which the README states as well. Before you migrate from BullMQ or pg-boss, read the atomic claim behaviour, because the guarantee that each job runs once comes from row locking rather than from a broker, and check the retry and snooze semantics against what your current workers expect. The licence is LGPL-3.0-or-later, the current release is 1.16.6 from 2026-10-01, and the last push was on 2026-10-14.
Frequently asked questions
What does Sidequest replace and what does it need?
It is a Redis-free background job processor for Node.js that persists jobs in PostgreSQL, MySQL, SQLite or MongoDB, positioning itself as a BullMQ and pg-boss alternative. It needs Node.js 22.6.0 or later and does not run on Bun yet.
How does Sidequest make sure a job runs only once?
Jobs are claimed atomically with `SELECT ... FOR UPDATE SKIP LOCKED` on Postgres and MySQL, so several workers polling the same table cannot take the same row. The guarantee therefore comes from the database's row locking rather than from a broker.
Which database backend should I use with Sidequest?
The PostgreSQL driver is the one the README marks as recommended, and SQLite is described as the default and not recommended for production, while MySQL and MongoDB drivers are also available. Each backend is a separate package, for example `@sidequest/postgres-backend`, because the main package does not include the drivers.
How do I enqueue a job with Sidequest?
Define a class that extends `Job` with an async `run` method, start Sidequest with `Sidequest.start({ backend: { driver, config } })`, and enqueue with `Sidequest.build(YourJob).enqueue(...args)`. The built-in dashboard then runs on its own port, which the example prints as http://localhost:8678.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sidequestjs-sidequest)Was this useful?