River 2024: Stability, new APIs, and production readiness
Time flies. It's already been six months since River was first released! Long enough that we wanted to provide a few updates on progress and newly added features since then.
Like might be expected for a brand new project, a majority of the time was spent fixing bugs, many of which were reported by the project's users. We didn't ship River until we were happy with its feature set, and although we did write a comprehensive test suite, there was a lot of code, and by extension a lot of code where small mistakes could appear. Recently, bug reports have been fewer and further between and more of our time has shifted back to implementing features, which we're interpreting as meaning that the most glaring problems have been ironed out.
The feature grid since launch
New features shipped since that first 0.0.1 release back in November:
A new
river/rivermigrate
package that provides a Go API to River's internal migrations framework, in addition to the existing CLI. Docs.A minimal
riverdriver/riverdatabasesql
driver for Go's built indatabase/sql
module, providing enough functionality to be compatible with Goose's Go migration API. Goose is the ecosystem's best migration tool (we use it for all our projects), and we wanted River to play nicely with it. Docs.The CLI has a new
river migrate-get
that dumps raw SQL for River migrations so it can be ported in other migration frameworks. Migration subcommands also support new--dry-run
and--show-sql
options to prospectively check the effects migrations would have. Docs.The CLI now has a
river bench
subcommand, providing an easy way of getting a rough idea of River's work throughput. Docs.river bench --database-url $DATABASE_URL --num-total-jobs 1_000_000
A new batch job completer that performs completion en masse for efficiency. Using the aforementioned benchmarking tool, we estimate that it increased River's throughput by ~4.5x, taking it to about 46,000 jobs/sec on a commodity MacBook Air.
Queue pausing and resuming where some or all queues can be temporarily paused as an operational lever. Docs.
A job cancellation API for River's client, which lets jobs be cancelled by ID. Docs.
A flexible job listing API, for retrieving jobs by state, queue, and other properties. Docs.
A job retrieval API, which fetches jobs by ID. Docs.
A job retry API for the client, allowing fine-grain job retries by job ID, outside a configured retry policy. Docs.
Poll only mode, which lets the River client run in environments where listen/notify isn't available, like PgBouncer in transaction pooling mode. Docs (see
Config.PollOnly
).An API for adding periodic jobs dynamically after a client has already started. Docs.
We've started cutting GitHub releases for new versions to make it easy to stay up to date with new features. We recommend updating River frequently (both the package dependency and the CLI) because it's under such active development.
API stability (minor changes only)
Notably, what hasn't happened are many backwards incompatible API changes. We did ship a small batch of breaking changes, but they were largely for APIs that were brand new, or those that are probably not in common use by most applications that use River. We tried to put a lot of thought in River's initial API before making it public to make API breakages as few and far between as possible, and we think it was largely a success given that the core APIs (e.g. creating and starting a client, working jobs, job insertion) have been stable since release.
Production ready?
We've been asked whether River is production ready. The answer "yes", or at least we think so.
River's test suite is very comprehensive, and users running River live helped identify bugs like a memory leak in random sources and another due to misuse of context cancellations where test coverage wasn't enough. We haven't gotten any new bug reports in months, which we take to be a good sign, but of course that's not definitive, so if you've had success (or unsuccess) running River in production, we'd love to hear about it.