Introduction
Core concepts of the emit.run system
Introduction
emit.run is a background job processing system with reliable, stateful job execution — built-in retries, timeouts, and real-time progress tracking.
Core Concepts
Spaces
Jobs are organized into spaces. A space belongs to an organization and acts as an isolated queue — it has its own jobs, API tokens, and WebSocket event stream.
Common patterns:
- One space per environment:
production,staging - One space per job type:
emails,video-processing,exports - One space per team or customer
Jobs
A job represents a unit of work. Each job has:
| Field | Description |
|---|---|
name | String identifier like send-email or generate-report |
payload | Optional JSON data your worker receives |
status | scheduled → pending → delivered → running → completed, dead, or killed |
maxRetries | How many times to retry on failure (default: 3) |
timeoutSeconds | Max execution time per attempt (default: 300s) |
scheduledFor | Optional future timestamp — delays the job until this time |
callbackUrl | Optional webhook URL — receives a POST when the job reaches a terminal state |
callbackHeaders | Optional custom headers sent with the callback (e.g., auth tokens) |
Job Lifecycle
- Created — Job enters
pendingstate and is queued in the space's dispatch queue. IfscheduledForis set, the job entersscheduledstate instead and waits until the specified time. - Scheduled (optional) — Job waits until
scheduledFortime, then automatically transitions topendingand enters the dispatch queue. - Delivered — Worker polls and receives the job; status moves to
deliveredand a delivery timeout starts. If the worker never acks, the job reverts topendingautomatically. - Running — Worker calls ack; status moves to
runningand the execution timeout starts - In progress — Worker sends strict progress updates (
percent+ user-facingmessage), checkpoint events, and optional custom events - Completed, Dead, or Killed — Worker calls complete (→
completed) or fail. On fail: retries remaining → re-queued aspending; no retries remaining →dead. An operator or control plane can call kill at any point before completion to force-stop the job askilled. - Callback — If
callbackUrlwas set, the system POSTs the result to that URL oncompleted,dead, orkilled
Worker Flow
Workers are simple HTTP clients that poll for work:
/spaces/:id/jobs/pollClaim up to 10 jobs. If the queue is empty, back off and poll again.
/jobs/:id/ackConfirm receipt. This moves the job to "running" and starts execution timeout tracking.
/jobs/:id/progressoptionalSend { percent, message } updates for user-facing progress.
/jobs/:id/keepaliveoptionalReset the timeout window during long-running work.
/jobs/:id/completeReport success with an optional result payload.
/jobs/:id/failReport failure. The job retries or transitions to dead when attempts are exhausted.
External control signal
/jobs/:id/killExternal operator/control-plane stop. After kill, worker mutations return 409 with code JOB_KILLED so in-flight work can exit quickly.
Scopes
API keys use granular scopes so you can give each client exactly the permissions it needs.
Granular scopes:
| Scope | What it allows |
|---|---|
jobs:create | Create new jobs |
jobs:read | List jobs, get job details, and use space/job streams |
jobs:poll | Claim pending jobs from the queue |
jobs:ack | Acknowledge receipt of a polled job |
jobs:progress | Send progress updates |
jobs:event | Publish checkpoint and custom events |
jobs:complete | Mark jobs as completed |
jobs:fail | Fail jobs (retry or mark dead) |
jobs:kill | Force-stop jobs and mark killed |
jobs:keepalive | Extend a running job's timeout |
jobs:read:progress | Read job progress via API or single-job WebSocket stream only |
Shorthand scopes (expand to multiple granular scopes):
| Shorthand | Expands to |
|---|---|
jobs:worker | jobs:read + jobs:poll + jobs:ack + jobs:progress + jobs:event + jobs:complete + jobs:fail + jobs:kill + jobs:keepalive + jobs:read:progress (shorthand for the full worker set) |
jobs:write | jobs:ack + jobs:progress + jobs:event + jobs:complete + jobs:fail + jobs:kill + jobs:keepalive |
Typical token setups:
| Use case | Scopes |
|---|---|
| Producer (submit jobs) | jobs:create |
| Worker (process jobs) | jobs:worker or select individual scopes |
| Dashboard / monitoring | jobs:read |
| Producer + monitor | jobs:create, jobs:read |
| Third-party client (live progress updates) | jobs:read:progress |