Workly

enqueue → HTTP delivery → retry → success

Background jobs are HTTP requests that happen later.

Workly is the open-source HTTP task queue. It delivers tasks to your endpoints, retries them until they succeed, runs your cron jobs as HTTP calls, and shows you exactly what happened. No workers, no broker, no guesswork.

A queue in the Workly dashboard: its backlog, recent activity and failed tasks grouped by error.

Your app only needs an endpoint.

Enqueue a task with a URL and a payload. Workly delivers it as a signed HTTP request. A 2xx and it's done; anything else is retried with backoff until it succeeds or runs out of attempts. Nothing to deploy next to your code, and it works with any language that can answer HTTP.

  • At-least-once delivery. A stable task ID on every attempt makes deduplication easy.
  • Local is production. The same binary runs on your laptop, in your cluster and hosted.
enqueue.py
from workly import Workly
workly = Workly() # WORKLY_URL, WORKLY_API_KEY
workly.tasks.enqueue(
"emails",
url="https://api.example.com/send-email",
payload={"user_id": 123},
)

You should never have to wonder what your queue is doing.

Every attempt is kept with its status code, error, response body and timing. A failed task says why Workly gave up and where to change that. The dashboard, metrics and history come with the server; there is nothing to bolt on.

A failed task in the Workly dashboard, explaining why it failed, with every attempt's response.

Retries that behave

Exponential backoff with jitter, Retry-After honoured, and a per-queue policy for what counts as retryable.

Rate and concurrency limits

Cap each queue's deliveries per second and in flight, so a backlog never floods the endpoint behind it.

Delayed tasks

Run a task in ten minutes or at a set time. Pause a queue during an incident; enqueueing keeps working.

Idempotency keys

Enqueue the same work twice and get the same task back, so retrying your own requests is safe.

Signed deliveries

Every request carries an HMAC signature, and the SDKs check it in one call.

Failures you can act on

Failed tasks stay, grouped by error. Fix the handler, then retry one group or the whole queue.

Prometheus metrics

Queue depth, delivery rate, latency and the age of the oldest due task, with example alerts.

SDKs and a CLI

Python and TypeScript SDKs, and a CLI for scripts and one-off fixes. Or plain HTTP.

Cron jobs, as HTTP calls you can see.

Schedules call your endpoint on a cron timetable, in your timezone. Every run is retried, signed and recorded like a task, with a run-now button and an answer to "why didn't the 03:00 report run?" Replace CronJob pods and Cloud Scheduler with the same server that runs your queues.

  • One run per slot. Even when a replica fails over at 03:00.
  • Overlaps and outages, handled. Skip a slot while the last run is still going, or catch up once after downtime.
  • Separate from your queues. Their own settings, history and metrics.
Read about schedules →
schedule.py
workly.schedules.put(
"nightly-report",
cron="0 3 * * *",
timezone="Europe/Stockholm",
url="https://api.example.com/reports/nightly",
)
nightly-report · runs
  • Oct 4, 03:00succeeded200 · 1.2s
  • Oct 3, 03:00succeeded200 after 2 attempts
  • Oct 2, 03:00skippedprevious run still going
  • Oct 1, 03:00failed503 Service Unavailable

Built for your coding agent, too.

Every Workly server speaks MCP. Point Claude Code, Cursor or Codex at it and your agent can read failures, replay a delivery against your local handler, and retry once the fix is in. Read-only unless you say otherwise.

Connect an agent →
>Why are tasks in the invoices queue failing in prod?
>Enqueue a test task to my local /tasks/send-email handler and tell me how it answered.
>I fixed the handler. Retry the failed tasks and check the first one succeeds.

Run it anywhere. Move without migrating.

The API is the same everywhere, so moving from your laptop to your cluster to workly.run means changing environment variables, not code.

On your laptop

workly dev

SQLite, no configuration, no Docker. The dashboard and an echo target are on localhost:7337.

Quickstart →

In your cluster

workly serve

One container plus Postgres, next to your apps. Endpoints on your private network are just URLs.

Self-hosting guide →

Hosted at workly.run

WORKLY_URL=https://api.workly.run

The same server, run for you: backups, upgrades and longer history, with nothing to operate.

Get started free →

Let us run it for you.

Hosted Workly is open, and free while it's in beta: the same server, with backups, upgrades and team access handled for you. Sign in with your email and you have a workspace and an API key in a minute. Self-hosting stays free, forever. See pricing.

Get started free