Quickstart
This guide gets you from zero to a working background job system in five steps. You will start an OJS server, enqueue a job from JavaScript, and process it with a worker.
Prerequisites
Section titled “Prerequisites”Step 1: Start the OJS server
Section titled “Step 1: Start the OJS server”Create a docker-compose.yml file:
services: redis: image: redis:7-alpine ports: - "6379:6379"
ojs-server: image: ghcr.io/openjobspec/ojs-backend-redis:latest ports: - "8080:8080" environment: REDIS_URL: redis://redis:6379 depends_on: - redisStart it:
docker compose up -dVerify the server is healthy:
curl http://localhost:8080/ojs/v1/healthYou should see {"status":"ok"} in the response.
Step 2: Install the SDK
Section titled “Step 2: Install the SDK”mkdir ojs-demo && cd ojs-demopnpm initpnpm add @openjobspec/sdkStep 3: Enqueue a job
Section titled “Step 3: Enqueue a job”Create enqueue.mjs:
import { OJSClient } from '@openjobspec/sdk';
const client = new OJSClient({ url: 'http://localhost:8080' });
const job = await client.enqueue('email.send', [ 'user@example.com', 'welcome',]);
console.log(`Enqueued job ${job.id} in state: ${job.state}`);Run it:
node enqueue.mjsYou should see output like:
Enqueued job 019461a8-1a2b-7c3d-8e4f-5a6b7c8d9e0f in state: availableStep 4: Start a worker
Section titled “Step 4: Start a worker”Create worker.mjs:
import { OJSWorker } from '@openjobspec/sdk';
const worker = new OJSWorker({ url: 'http://localhost:8080', queues: ['default'], concurrency: 5,});
worker.handle('email.send', async (ctx) => { const [to, template] = ctx.args; console.log(`Sending "${template}" email to ${to}`);
// Your email logic goes here. // For now, just simulate some work. await new Promise((r) => setTimeout(r, 500));
return { delivered: true };});
// Graceful shutdown on Ctrl+Cprocess.on('SIGINT', () => worker.stop());process.on('SIGTERM', () => worker.stop());
await worker.start();console.log('Worker started, waiting for jobs...');Run the worker:
node worker.mjsYou should see:
Worker started, waiting for jobs...Sending "welcome" email to user@example.comStep 5: Check the job status
Section titled “Step 5: Check the job status”In a separate terminal, check the job:
curl http://localhost:8080/ojs/v1/jobs/<job-id>Replace <job-id> with the ID printed in Step 3. The response shows the completed job with its result:
{ "job": { "id": "019461a8-1a2b-7c3d-8e4f-5a6b7c8d9e0f", "type": "email.send", "state": "completed", "attempt": 1, "result": { "delivered": true } }}What just happened?
Section titled “What just happened?”- The OJS server (Redis backend) started and connected to Redis.
- Your client sent a
POST /ojs/v1/jobsrequest with the job envelope. The server assigned a UUIDv7 ID, set the state toavailable, and stored the job in Redis. - Your worker polled
POST /ojs/v1/workers/fetch, claimed the job (state changed toactive), and ran your handler. - The handler succeeded, so the worker sent
POST /ojs/v1/workers/ack. The server set the state tocompletedand stored the result.
All retry logic, scheduling, and state management happened server-side. Your client and worker code stayed simple.
Next steps
Section titled “Next steps”- Read Core Concepts to understand the job envelope, lifecycle states, and operations.
- Explore SDKs for Go, Python, Java, Rust, and Ruby.
- Try the PostgreSQL backend if you prefer SQL over Redis.
- Add retry policies, scheduled jobs, or workflows to your jobs.