npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lomatina/queue-lite

v0.1.0

Published

TypeScript-first, durable job queue for Node/Bun. No Redis — uses the database you already have (SQLite, Postgres, or in-memory).

Readme

queue-lite

A TypeScript-first, durable job queue for Node/Bun — without Redis. It uses the database you already have: SQLite by default (zero native deps via bun:sqlite), Postgres as a drop-in for multi-server, and an in-memory backend for tests.

import { z } from "zod";
import { createQueue, defineJob, SqliteAdapter } from "queue-lite";

const sendEmail = defineJob({
  name: "sendEmail",
  schema: z.object({ to: z.string().email(), subject: z.string() }),
  handler: async ({ payload }) => {
    await mailer.send(payload.to, payload.subject);
  },
});

const queue = createQueue({
  storage: new SqliteAdapter("queue.db"),
  jobs: [sendEmail],
  worker: { concurrency: 5 },
});

await queue.start();

await queue.enqueue("sendEmail", { to: "[email protected]", subject: "Welcome!" });
// compile error - wrong payload shape:
// await queue.enqueue("sendEmail", { to: "[email protected]" });
// compile error - unknown job name:
// await queue.enqueue("sendEmial", { to: "...", subject: "..." });

Why

Every mature Node job queue needs Redis: friction in dev, cost in deploy, a coordination point at scale. queue-lite removes that — jobs live in your existing database, survive restarts, retry on failure, and run scheduled work without a cron daemon. When you truly outgrow it, switch to Postgres by changing one line.

Features

  • Type-safe enqueue — payloads are inferred from each job's Zod schema; wrong name or shape is a compile error, and everything is validated again at runtime.
  • Durable — jobs are written to storage before returning; nothing is lost on crash or deploy.
  • Retries with backoff — fixed or exponential, with jitter, configurable per job.
  • Delays and priorities — run a job later (delayMs/runAt) or ahead of others.
  • Cron schedules — recurring jobs that fire exactly once across instances.
  • Lifecycle eventsenqueued, started, completed, failed, retried, stalled for logging/metrics/alerting.
  • Stalled-job recovery — leases expire and orphaned jobs are reclaimed.
  • CLI — inspect and manage the queue from your terminal.
  • Pluggable storage — SQLite, Postgres, Memory; one interface, easy to extend.

Install

bun add queue-lite zod
# Postgres backend (optional):
bun add postgres

Storage backends

import { SqliteAdapter, PostgresAdapter, MemoryAdapter } from "queue-lite";

new SqliteAdapter("queue.db");            // file-backed (default)
new SqliteAdapter(":memory:");            // ephemeral
new PostgresAdapter(process.env.PG_URL!); // multi-server
new MemoryAdapter();                      // tests

Switching backends changes only this one line — your job code is unchanged.

Scheduling, delays, priorities

// Every weekday at 9am
await queue.schedule("dailyReport", "0 9 * * 1-5", { team: "growth" });

// Run 3 days from now
await queue.enqueue("followUp", { userId }, { delayMs: 3 * 24 * 60 * 60 * 1000 });

// Jump the line
await queue.enqueue("chargeCard", { invoiceId }, { priority: 10 });

// Dedupe
await queue.enqueue("syncUser", { userId }, { idempotencyKey: `sync:${userId}` });

Inspecting state

await queue.stats();           // { pending, active, failed, ... }
await queue.list({ status: "failed", limit: 20 });
await queue.getJob(id);
await queue.history(id);       // every attempt + error
await queue.retry(id);         // requeue a failed job
await queue.cancel(id);        // cancel a pending/delayed job

CLI

queue-lite stats --db queue.db
queue-lite list --status failed
queue-lite show <job-id>
queue-lite retry <job-id>
queue-lite cancel <job-id>
queue-lite stats --pg "$PG_URL" --json

Use --db <path> / QUEUE_LITE_DB for SQLite or --pg <conn> / QUEUE_LITE_PG for Postgres, and --json for machine-readable output.

Testing your jobs

Use the in-memory adapter and a FakeClock to drive the worker deterministically:

import { createQueue, MemoryAdapter, FakeClock } from "queue-lite";

const clock = new FakeClock(0);
const queue = createQueue({ storage: new MemoryAdapter(), jobs: [myJob], clock });

await queue.enqueue("myJob", { /* ... */ });
await queue.runWorkerOnce();           // process all ready jobs, no real timers
expect((await queue.stats()).completed).toBe(1);

Roadmap

The StorageAdapter interface and the CLI's read layer are deliberate seams, so these land without breaking the public API:

  • More databases — MySQL/MariaDB, LibSQL/Turso, MongoDB (implement the adapter and pass the conformance suite).
  • Richer CLIwork (run a worker), purge, schedules, --watch live tail.
  • Web dashboard — an optional queue-lite/web served via Bun.serve, reusing the same adapter calls and streaming queue.events over SSE.

Not for

Extreme-throughput pipelines (tens of thousands of jobs/sec) — reach for BullMQ and Redis. queue-lite is for everything else, with a clear upgrade path.

License

MIT