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-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

FeatureMemoryPostgreSQLSQLite
Job CRUDYesYesYes
Bulk insertYesYesYes
DeduplicationYesYesYes
Priority orderingYesYesYes
FIFO / LIFOYesYesYes
Delayed jobsYesYesYes
Pause / ResumeYesYesYes
Stalled job detectionYesYesYes
Job flows (parent-child)YesYesYes
Groups (round-robin)YesYesYes
Auto-migrationsN/AYesYes
Cross-process eventsNoYes (LISTEN/NOTIFY)No (in-process only)
Connection poolingN/AYesN/A
TransactionsN/AYesYes (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 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 (Redis, DynamoDB, etc.), you can implement StoreInterface directly. See the custom store guide.

Released under the MIT License.