Databases

By Artyom Kazak aka @availablegreen
Last update: January 10, 2021

Multi-SQL-database libraries

Beam, but eh.

Beam supports Postgres, MySQL, and Sqlite, which is currently all I need.

The good thing about Beam is that it doesn't use Template Haskell — I am very comfortable with TH, but see my Reddit comment for more info about why I think TH is not great. Hence Beam and not Persistent/Esqueleto.

The bad thing about Beam is that the machinery Beam uses instead of Template Haskell is pretty overwhelming. I spent a while learning how Beam works internally and now I can do interesting things with it, but otherwise — meh.

Beam was maintained pretty slowly in 2019, and a lot of things had to be patched (at Juspay, by other people) to get Beam into shape, particularly for MySQL. See the fork at juspay/beam.

Note that any functions in Beam that use Bool will generate very inefficient queries. Use SqlBool wherever possible.

See also: William Yao's Which type-safe database library should you use?, listing Opaleye and Selda as favorites.

Update Jan 10, 2021: I am told that Esqueleto significantly improved in v3.4, so perhaps we do have a good multi-DB library in Haskell after all. I haven't checked it myself yet.

PostgreSQL specifically

Maybe Opaleye? Or if you want something lower-level and non-typesafe, then hasql and hasql-th.

For PostgreSQL specifically, Opaleye might be a better choice — not least because it doesn't need all the horrible machinery necessary to abstract over database engines. This is supported by the Which type-safe database library should you use? post I linked above.

Redis (key-value and data structure store)

Probably hedis, even though it's low-level.

There are some higher-level libraries, but 'hedis' seems to be a safe and dumb choice, even if cumbersome.

Cassandra (wide column store)

Probably cql-io.

We used 'cql-io' at Wire. It definitely works in production, or at least it worked in production in 2019. I'm not sure if anything else even exists.

MongoDB (document store)

Probably raw mongoDB?

It doesn't look like there is any choice — either use raw mongoDB, which is a raw client library, or persistent-mongoDB, which uses 'mongoDB' to create a higher-level Persistent backend that you can work with. Given that Persistent was made for SQL databases, I'd probably just go with raw 'mongoDB' for now — but I haven't used either.