Background jobs for .NET that say what they promise
Write a job to PostgreSQL, SQLite or Redis. A worker in your app, or in its own process, picks it up and runs your handler. Schedules, retries, rate limits, a dashboard and a CLI come with it.
Pick a store. Your jobs, handlers and registration stay the same.
PostgreSQL
Runwick.Postgres
The reference store. Producers and workers on many hosts, and jobs that commit inside your own transaction.
SQLite
Runwick.Sqlite
One file on one machine. Durable writes, no server to run, and the same transactional completion.
Redis
Runwick.Redis
One durable primary with append-only fsync. Many hosts; use the outbox to tie jobs to business data.
Built for jobs that matter
A lost welcome email is an annoyance. A lost invoice is not. Runwick is careful about the gap between the two, and tells you exactly where its guarantees stop.
It says what it promises
Delivery is at-least-once, cancellation is cooperative, and the docs list what Runwick does not claim. The one exactly-once case is completing a job in the same transaction as your own work.
One API, three stores
Jobs, handlers and registration are the same everywhere. Moving from SQLite on a laptop to PostgreSQL in production changes one line.
Operations are part of the library
A management HTTP API, a web dashboard and a runwick command line share one permission model and one audit trail. There is no anonymous mode.
Observable from day one
OpenTelemetry traces and metrics with fixed names, structured logs, health checks per role, a Grafana dashboard and Prometheus alert rules in the box.
invoice.send
2 attempts · max 3
pending09:14:02.118
Dispatched. The store confirmed the write.
running09:14:02.164
Attempt 1 on worker web-2
retrying09:14:03.902
Billing API answered 503. Next attempt in about 5 s.
running09:14:09.217
Attempt 2 on worker web-1, same idempotency key
succeeded09:14:09.629
One invoice sent. The retry did not send a second.
See every job
The dashboard ships inside the Runwick.Dashboard package, with no Node at runtime. It shows each job's status history, attempts and the resources they used, and lets operators cancel, retry and pause queues with the same permissions as the API.

How it works
- 1
Dispatch
Your app calls DispatchAsync. It returns only after the store has confirmed the write, so a job you were told about is a job that exists.
- 2
Store
The job waits in PostgreSQL, SQLite or Redis with its queue, priority, schedule and limits. Nothing lives only in memory.
- 3
Run
A worker, in your app or a separate process, leases the job, runs your handler and records the outcome. Failures retry with backoff.
Working with an AI agent?
The whole documentation is available as plain text, and the runwick CLI has an agent mode with stable, machine-readable output.