Get started
Quickstart
Create a cluster, send your first job, and run it in a worker.
You'll create a free cluster, send a send-welcome-email job to it, and run that job in a worker on your machine. You need Node.js 20.3 or later, Go 1.23 or later, or just curl.
Create a cluster
Sign in at emit.run and choose New cluster. Give it a name, pick a region and choose the Free plan. It needs no card.
A cluster is your own emit service, with its own address. Its Overview page shows that address, the endpoint your code connects to.
Create an API token
Open the cluster's Tokens tab and create a token. Leave Spaces blank and keep the scopes it starts with:
create,workandread.The secret is shown once. Copy the
.envblock it offers, which holds both values you need:.envEMIT_URL=https://<your cluster's endpoint> EMIT_TOKEN=emit_...Load them into your shell with
export $(cat .env), or however your project reads.envfiles.Install an SDK
npm init -y npm pkg set type=module # the examples use top-level await npm install @emit.run/sdkgo mod init welcome go get github.com/emit-run/sdk-go# Nothing to install: every step below is a plain HTTP request.Run a worker
A worker asks emit for jobs by name, runs them, and reports back. Jobs live in a space, a named queue; these examples use one called
emails, which is created by its first job, so the worker can start before it exists. Returning a value completes the job. Throwing, or returning an error, fails this attempt, and emit tries it again later.// worker.ts import { Emit } from "@emit.run/sdk"; const emit = new Emit({ url: process.env.EMIT_URL!, token: process.env.EMIT_TOKEN!, space: "emails", }); type Welcome = { userId: string; email: string }; const worker = emit.worker<Welcome>({ names: ["send-welcome-email"] }, async (job) => { await job.progress(50, "rendering"); console.log(`sending the welcome email to ${job.payload.email}`); return { sent: true }; }); // Finish the jobs in hand before the process exits. process.once("SIGINT", () => worker.stop());// main.go package main import ( "context" "log" "os" "os/signal" emit "github.com/emit-run/sdk-go" ) type Welcome struct { UserID string `json:"userId"` Email string `json:"email"` } func main() { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() c := emit.New(emit.Options{URL: os.Getenv("EMIT_URL"), Token: os.Getenv("EMIT_TOKEN"), Space: "emails"}) worker := c.Worker(ctx, emit.WorkerOptions{Names: []string{"send-welcome-email"}}, func(ctx context.Context, job *emit.HeldJob) (any, error) { var in Welcome if err := job.Decode(&in); err != nil { return nil, emit.Unrecoverable(err) // a payload we can't read won't get better on a retry } if err := job.Progress(ctx, 50, "rendering"); err != nil { return nil, err } log.Printf("sending the welcome email to %s", in.Email) return map[string]bool{"sent": true}, nil }) select { case <-ctx.Done(): // Ctrl-C case <-worker.Done(): // the worker stopped on its own, for example a revoked token } if err := worker.Stop(); err != nil { log.Fatal(err) } }# Ask for one send-welcome-email job, waiting up to 30 seconds for one to arrive. curl -s "$EMIT_URL/v1/spaces/emails/jobs:claim" \ -H "Authorization: Bearer $EMIT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"names": ["send-welcome-email"], "count": 1, "waitMs": 30000}' # The answer holds the job's id and attempt. Report the result with both: curl -s "$EMIT_URL/v1/spaces/emails/jobs:report" \ -H "Authorization: Bearer $EMIT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"id": "<job id>", "attempt": 1, "complete": {"result": {"sent": true}}}'Start it and leave it running:
npx tsx worker.ts(npx fetchestsxthe first time; on Node.js 22.18 or later,node worker.tsworks too), orgo run ..Send a job
From another terminal, create a job and wait for its result (
npx tsx send.ts, orgo run ./send).// send.ts import { Emit } from "@emit.run/sdk"; const emit = new Emit({ url: process.env.EMIT_URL!, token: process.env.EMIT_TOKEN!, space: "emails", }); const { id } = await emit.jobs.create("send-welcome-email", { userId: "usr_42", email: "ada@example.com", }); console.log("created", id); const result = await emit.jobs.result(id); // follows the job until it ends console.log("result", result); // { sent: true }// send/main.go package main import ( "context" "log" "os" emit "github.com/emit-run/sdk-go" ) func main() { ctx := context.Background() c := emit.New(emit.Options{URL: os.Getenv("EMIT_URL"), Token: os.Getenv("EMIT_TOKEN"), Space: "emails"}) created, err := c.Jobs.Create(ctx, emit.NewJob{ Name: "send-welcome-email", Payload: map[string]string{"userId": "usr_42", "email": "ada@example.com"}, }) if err != nil { log.Fatal(err) } log.Printf("created %s", created.ID) var result struct { Sent bool `json:"sent"` } if err := c.Jobs.Result(ctx, created.ID, &result); err != nil { // follows the job until it ends log.Fatal(err) } log.Printf("sent: %v", result.Sent) }curl -s "$EMIT_URL/v1/spaces/emails/jobs" \ -H "Authorization: Bearer $EMIT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "send-welcome-email", "payload": {"userId": "usr_42", "email": "ada@example.com"}}' # {"created":[{"id":"01M3QSGN0103P7EGVBX9D5NTSN","outcome":"NEW","attempt":0,...}]} # Read it back: its status, progress and result. curl -s "$EMIT_URL/v1/spaces/emails/jobs/01M3QSGN0103P7EGVBX9D5NTSN" \ -H "Authorization: Bearer $EMIT_TOKEN"The worker prints the email address, and the sender prints
{ sent: true }. In the dashboard, open theemailsspace from the cluster's Spaces tab to see the job with its progress and result.
Next
Retries, delays, idempotency keys and callbacks.
Follow a job live from your frontend.
Chain steps, sleep and wait for events in one function.
Every option of the client and the worker.