Slick 3: Reactive Streams for Asynchronous Database Access in Scala

| by Mirko Stocker on May 09, 2015. Estimated reading time: 3 minutes |

Slick, Typesafe's database query and access library for Scala, received a major overhaul in the just released version 3.0. Also dubbed "Reactive Slick", it introduces a new API to compose and run database queries in a reactive way. Reactive meaning that it supports the Reactive Streams API, an "initiative to provide a standard for asynchronous stream processing with non-blocking back pressure" (other implementations include Akka, MongoDB, RxJava, Vert.x, etc.) and supports building applications according to the Reactive Manifesto.

Database queries in Slick can be written as if they were operating on Scala collections, supporting the same vocabulary and similar operations (even though this illusion fails on more complex expressions). As a bonus, because the queries are not just plain strings, they are being type-checked by the compiler. An example of a simple join of two tables and a where-clause:

val q2 = for {
  c <- coffees if c.price < 9.0
  s <- suppliers if === c.supID
} yield (,

An equivalent SQL code could look like this:

select c.COF_NAME, s.SUP_NAME from COFFEES c, SUPPLIERS s where c.PRICE < 9.0 and s.SUP_ID = c.SUP_ID;

While the query API has remained largely unchanged in Slick 3, a query now returns a DBIOAction instead of an actual result (the old APIs are deprecated and will be removed in 3.1). Such actions can then be combined and in the end are passed to the database, where they will eventually be run. Here's an example of such a Slick 3 style query:

val q = for (c <- coffees) yield
val a = q.result
val f: Future[Seq[String]] =

f.onSuccess { case s => println(s"Result: $s") }

compared with the previous API:

val q = for (c <- coffees) yield
val result = db.withSession {
  implicit session =>
  val s = q.list // <- takes session implicitly
  println(s"Result: $s")

The main benefit of the new approach is that it's completely asynchronous, so running a database-query won't block the calling thread. Also, results from the database can now be streamed. In combination with, for example, the Play Framework that supports Reactive Streams, this then frees up your request handling thread as quickly as possible.

InfoQ talked to Slick Tech-Lead Stefan Zeiger to learn more about the new release and their plans for the future.

InfoQ: The new API seems to mostly affect how queries are run, have there been any changes to how queries are constructed?

There are no fundamental changes to the way you write queries but there a two big new features: Outer joins are now correctly typed, returning an Option for one side (or both in case of a full outer join). This makes outer joins with mapped data types or over more than two tables straight-forward to write, where you previously had to perform some non-obvious and non-trivial mapping yourself in every query. The other big feature is the tsql interpolator that allows static verification and type inference for embedded SQL statements. Instead of waiting until runtime to discover errors in manually written SQL, the Scala compiler can now let the database perform the checks at compile-time.

InfoQ: Do you have any plans to create a Java API for Slick that makes use of Java 8's new Streams and lambdas, similar to Play or Akka's Java APIs?

Yes, this is something we would like to do in the near future in order to complete our full-stack solution for Java developers.

InfoQ: Does streaming and the new IO-API work will all databases or are there limitations?

The DBIO API is implemented on top of JDBC and works with all existing drivers. We are also looking into improved native support for databases with existing asynchronous drivers.

InfoQ: Can you share your plans for Slick 3.1 or 4.0?

The major feature currently in the works for Slick 3.1 is an improved query compiler back-end which generates simpler SQL code. This will make the generated code more readable for all users and should also provide some performance benefits, especially on MySQL where joins, as they are currently generated by Slick, often cannot use an index. As part of our commercial offering in the Reactive Platform we will add monitoring features specifically for Slick.

For the full list of changes, see the release announcement and don't forget to check the upgrade guide. To learn more about Slick 3, watch this ScalaDays talk by Stefan Zeiger.

Rate this Article


Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Ideally the database driver should also support async IO by Faisal Waris

Otherwise you are getting half the benefit.

I think only SQL Server supports async IO for relational databases. I know of J2EE-Oracle applications regularly running into thread starvation under load.

SQL Server asynchronous connection string setting

Re: Ideally the database driver should also support async IO by Lukas Eder

PostgreSQL does, too

More complex queries by Lukas Eder

Example queries expressed in Slick are always extremely simple, whereas the use-cases of asynchronous querying against an RDBMS seems to be most beneficial in analytics and reporting scenarios - yet I have thus far failed to see any relevant examples in that space.

Would be interesting to hear what the community thinks of that.

More complex queries by Lukas Eder

- (ignore this, form was submitted twice) -

Re: More complex queries by Sanjarbek Amatov

You are right completely! Official documentation is not enough to do something more complex than simple queries. I am newbie in slick. And that is what I feel when learning this tool.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

5 Discuss