River makes use of drivers to insulate itself from third party packages, enabling use of different databases, database packages, and new major versions. River currently includes riverpgxv5 for Postgres, riversqlite for SQLite, and riverdatabasesql for Postgres through Go's built-in database/sql. For Postgres, riverpgxv5 is 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 access to the target database.
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.