The open, language-agnostic standard for background job processing.
Specification · Website · Playground · Discussions
Open Job Spec (OJS) is a vendor-neutral envelope format and protocol for background job processing. It defines a universal standard so that producers, consumers, and backends can interoperate regardless of language, framework, or infrastructure.
OJS provides:
- 🎯 Universal job envelope — A single schema for job metadata, args, and lifecycle state
- 🔄 8-state lifecycle —
scheduled → available → pending → active → completed/retryable/cancelled/discarded - 🌐 Protocol bindings — HTTP and gRPC, with extensible transport support
- 📦 Wire formats — JSON and Protobuf serialization
- 🔌 Extensions — Retries, cron scheduling, workflows, unique jobs, middleware, and events
Think of it as CloudEvents, but for background jobs.
| Repository | Description |
|---|---|
| spec | Core specification, extensions, and RFC process |
| ojs-json-schema | JSON Schema (draft 2020-12) validation definitions |
| ojs-proto | Protocol Buffer / gRPC service definitions |
| ojs-conformance | Language-agnostic conformance test suite (5 levels) |
| Repository | Stack | Status |
|---|---|---|
| ojs-backend-redis | Go + Redis 7 + Lua scripts | |
| ojs-backend-postgres | Go + PostgreSQL 15 + SKIP LOCKED |
| Repository | Language | Package |
|---|---|---|
| ojs-go-sdk | Go | go get github.com/openjobspec/ojs-go-sdk |
| ojs-js-sdk | TypeScript / JavaScript | npm install @openjobspec/sdk |
| ojs-python-sdk | Python | pip install openjobspec |
| ojs-java-sdk | Java 21+ | Maven Central |
| ojs-rust-sdk | Rust | cargo add openjobspec |
| ojs-ruby-sdk | Ruby | gem install openjobspec |
| Repository | Description |
|---|---|
| ojs-playground | Interactive browser-based IDE — define jobs, visualize lifecycles, simulate retries |
| website | Source for openjobspec.org |
# Enqueue a job via HTTP
curl -X POST http://localhost:8080/api/v1/jobs \
-H "Content-Type: application/json" \
-d '{
"type": "email.send",
"args": ["user@example.com", "Welcome!", "Thanks for signing up."],
"queue": "default"
}'Every SDK follows the same pattern — Client (producer) and Worker (consumer):
// TypeScript — Enqueue
const client = new OJSClient({ baseUrl: "http://localhost:8080" });
await client.enqueue({ type: "email.send", args: ["user@example.com"] });
// TypeScript — Process
const worker = new OJSWorker({ baseUrl: "http://localhost:8080" });
worker.register("email.send", async (job) => {
await sendEmail(...job.args);
});
await worker.start();OJS follows a three-layer model inspired by CloudEvents:
┌─────────────────────────────────────────────┐
│ Layer 3: Protocol Bindings │
│ HTTP · gRPC │
├─────────────────────────────────────────────┤
│ Layer 2: Wire Formats │
│ JSON · Protobuf │
├─────────────────────────────────────────────┤
│ Layer 1: Core Specification │
│ Job Envelope · Lifecycle · Operations │
└─────────────────────────────────────────────┘
We welcome contributions of all kinds. Here's how you can help:
- 🐛 Report bugs — Found an issue? Open a bug report
- 💡 Request features — Have an idea? Submit a feature request
- 📝 Propose spec changes — All changes go through our RFC process
- 🔧 Build an implementation — Write an OJS backend or SDK in a new language
- ✅ Run conformance tests — Validate implementations with our test suite
- 💬 Join the discussion — GitHub Discussions
Please read our Contributing Guide and Code of Conduct before participating.
All Open Job Spec projects are licensed under the Apache License 2.0.