River makes use of drivers to insulate itself from third party packages, enabling future use of other database packages or new major versions. Currently, the two supported drivers are riverdatabasesql
and riverpgxv5
, with riverpgxv5
being the recommended option.
Drivers wrap third party packages
The River Client
takes a generic TTx
type parameter representing the type of the transaction in use for functions like InsertTx
and InsertManyTx
. TTx
is derived from the client's driver, an agnostic interface to a third party package that provides protocol access to Postgres.
Most of the time, the only time code references a database driver is when it's initializing a River client. NewClient
takes a driver as its first parameter, and the driver wraps a database pool:
import "github.com/riverqueue/river"import "github.com/riverqueue/river/riverdriver/riverpgxv5"
...
dbPool, err := pgxpool.New(ctx, os.Getenv("DATABASE_URL"))if err != nil { panic(err)}defer dbPool.Close()
riverClient, err := river.NewClient(riverpgxv5.New(dbPool), &river.Config{ ...})if err != nil { panic(err)}
See the InsertAndWork
example for complete code.
Known limitations of riverdatabasesql
The riverdatabasesql
driver is limited compared to Pgx's in that database/sql
doesn't support a way to use Postgres' LISTEN
feature, so workers don't immediately receive signals when jobs are inserted. Instead they enter "poll only mode", which polls periodically for newly available jobs.
In general, riverpgxv5
should be considered River's main supported driver. Pgx is performant, feature complete, production hardened, and well maintained, while Go's database/sql
is broadly considered misdesigned, and too generic to provide access to important Postgres features.