Fast and reliable
background jobs in Go.
Atomic, transaction-safe job queueing for Go applications. Backed by PostgreSQL and built to scale.
Transactional enqueueing simplifies everything.
River jobs never run before your transaction completes, and are never lost. If your API's transaction succeeds, your job will be enqueued—period.
Compared to working with external job queues like Redis, this means a simpler development model that lets you build more reliable applications more quickly. For Go applications built on Postgres, this also means no added services to manage.
func createUser( /* ... */) (*User, error) {
tx, err := dbPool.Begin(ctx)
if err != nil {
return nil, err
}
defer tx.Rollback(ctx)
// Create the new user record:
user, err := insertUser(ctx, tx, email)
if err != nil {
return nil, err
}
// Enqueue a job to send the user an onboarding email:
if _, err = riverClient.InsertTx(ctx, tx,
SendOnboardingEmailArgs{UserID: user.ID},
nil,
); err != nil {
return nil, err
}
// Atomically commit both the user record and the job:
if err := tx.Commit(ctx); err != nil {
return nil, err
}
return user, nil
}
Batteries included
The features you need.
River is fully-featured so you can focus on building your app instead of chasing down bugs and distributed systems edge cases.
Core Features | |
---|---|
Multiple isolated queues | |
Unique jobs | |
Prioritization | |
Recurring (cron) Jobs | |
Snoozing | |
Transactional job completion | |
Test helpers |
Operations | |
---|---|
Web interface | |
Pause and resume queues | |
Automatic retries | |
Error reporting | |
Telemetry integrations | |
No added service dependencies | |
Global concurrency limits | Pro |
Advanced | |
---|---|
Recorded output | |
Workflows | Pro |
Sequences | Pro |
Encrypted jobs | Pro |
A better workflow with River Pro
River Pro extends the River open source project with time-saving features and commercial support. Available through a paid subscription.


Workflows
Break down complex workflows into discrete tasks, including fan-out and fan-in execution.


Concurrency limits
Globally limit concurrent jobs with granular partitioning. Scale your workloads with precision and confidence.
Sequences
Run sequences of jobs in strict order, each running independently in parallel.
No limits
Self-hosted and scalable
No new external services—just use your existing database. No per-workflow pricing.
Keep it going
Support River's development
Help ensure the sustainable maintenance and development of River.

Thoughtfully designed for modern Go.
River is designed by experienced Go developers to fit the conventions of the Go ecosystem. It leverages generics to provide strongly typed, structured arguments to workers.
// Each worker has a corresponding args type:
type SendEmailArgs struct {
UserID int64
}
func (args SendEmailArgs) Kind() string { return "SendEmail" }
type SendEmailWorker struct {
river.WorkerDefaults[SendEmailArgs]
}
// Work receives a typed *Job[T] to process:
func (w *SendEmailWorker) Work(ctx context.Context, j *Job[SendEmailArgs]) error {
user, err := getUser(ctx, j.Args.UserID)
if err != nil {
return err
}
return sendOnboardingEmail(user.email)
}
Built for humans
Easy to operate and develop. ✨
River ships with an optional self-hosted web interface called River UI. Whether you're trying to diagnose an ongoing incident, perusing for details on erroring jobs, or merely trying to see whether your jobs are working correctly in development, a visual interface makes life easier.
- Gain insights.
- Tune your system by keeping an eye on queue depth and throughput.
- Control jobs and queues.
- Cancel, retry, or delete jobs. Pause entire queues to halt job processing, or adjust concurrency limits (Pro only).
- Find bugs.
- Discover slow, stuck, or erroring jobs. Uncover hidden production issues.
- Faster development.
- See whether your jobs are working as you write them. Quickly iterate your way to a working system.
- Open source, self-hosted.
- Keep your data on your systems. Lightweight and stateless, with no added service dependencies.
- Dark mode.
- Because nobody wants to use a bright white website when responding to an outage at 2am.
Stay updated.
We're hard at work on more advanced features including rate limiting, and concurrency controls. Sign up to get updates on our progress.