Skip to content

Store Backends

Conveyor is a multi-backend job queue. Every store implements the same StoreInterface contract from @conveyor/shared, so switching backends means changing a single line of configuration.

Available Stores

PackageBackendBest ForPersistenceEventsRuntime
@conveyor/store-memoryIn-memory MapTesting, dev, prototypingNoneSynchronous callbacksAll
@conveyor/store-pgPostgreSQLProduction, multi-processFullLISTEN/NOTIFYAll
@conveyor/store-redisRedis 7+BullMQ migrants, low-latency, multi-processAOF / RDB (tune)Pub/SubAll
@conveyor/store-sqlite-nodeSQLite (node:sqlite)Single-process productionFullPollingNode 22.13+, Deno 2.2+
@conveyor/store-sqlite-bunSQLite (bun:sqlite)Single-process productionFullPollingBun 1.2+
@conveyor/store-sqlite-denoSQLite (@db/sqlite)Single-process productionFullPollingDeno 2.2+

All three SQLite packages share a common base in @conveyor/store-sqlite-core and expose an identical API.

Feature Support Matrix

FeatureMemoryPostgreSQLRedisSQLite
Job CRUDYesYesYesYes
Bulk insertYesYesYesYes
DeduplicationYesYesYesYes
Priority orderingYesYesNot yet (FIFO in v1)Yes
FIFO / LIFOYesYesYesYes
Delayed jobsYesYesYesYes
Pause / ResumeYesYesYesYes
Stalled job detectionYesYesYesYes
Job flows (parent-child)YesYesYesYes
GroupsYes (round-robin)Yes (round-robin)Yes (first-fit in v1)Yes (round-robin)
Auto-migrationsN/AYesN/A (schemaless)Yes
Cross-process eventsNoYes (LISTEN/NOTIFY)Yes (Pub/Sub, best-effort)No (in-process only)
Connection poolingN/AYesSingle client + subscriberN/A
TransactionsN/AYesLua scripts (atomic)Yes (BEGIN IMMEDIATE)

Choosing a Store

Use MemoryStore when:

  • Writing tests (fast, deterministic, no setup)
  • Prototyping or building CLI tools
  • You do not need persistence or multi-process coordination

Use PgStore when:

  • Running in production with multiple processes or servers
  • You need cross-process event delivery (LISTEN/NOTIFY)
  • You already have a PostgreSQL instance available
  • You need full transactional guarantees with row-level locking

Use RedisStore when:

  • You already operate Redis in production (managed or self-hosted) and want zero new infra
  • You are migrating from BullMQ and want to keep the same datastore
  • Your workload leans on high-throughput, short-lived jobs where Redis's in-memory profile shines

Use a SQLite store when:

  • Running a single-process server or worker
  • You need persistence but not a separate database server
  • You want an embedded database with minimal operational overhead

Quick Start

Every store follows the same pattern:

ts
import { Queue, Worker } from '@conveyor/core';

// 1. Create the store
const store = new SomeStore({/* store-specific options */});

// 2. Connect (runs migrations if applicable)
await store.connect();

// 3. Use with Queue and Worker
const queue = new Queue('my-queue', { store });
const worker = new Worker('my-queue', async (job) => {
  // process job
}, { store });

// 4. Cleanup
await worker.close();
await queue.close();
await store.disconnect();

Building a Custom Store

If the built-in stores do not cover your use case (DynamoDB, Cloudflare D1, etc.), you can implement StoreInterface directly. See the custom store guide.

Released under the MIT License.