Skip to main content

Use ZIO Blocks with ZIO, cats-effect or Plain Scala

ZIO Blocks needs no effect system, so the question for most projects is not whether a block fits, but where its calls go. This page answers it in one table for each kind of call. How to Use ZIO Blocks in a ZIO or cats-effect Application shows every case with complete, runnable code.

In Plain Scala​

In a plain Scala program, there is nothing to arrange: call a block where you need it. Decoding returns an Either, a scope closes its resources when its block ends, and a stream runs when you call one of its run methods. Every example in this Getting Started section is plain Scala.

The one choice you still make is about threads. Some calls block the calling thread until they finish, such as a database query or Stream#runCollect on the JVM. In a command-line tool or a batch job that is fine; in a server, run them on a thread pool meant for blocking work, or use the Async variants that the blocks provide.

In a ZIO or cats-effect Application​

In an application that already runs on ZIO or cats-effect, each kind of ZIO Blocks call has one place where it belongs. Pure calls stay as they are, blocking calls move to the effect system's blocking pool, and resources and streams are wrapped once so that interruption and cleanup work across the boundary:

Kind of callExampleIn ZIOIn cats-effect
Pure and fasttoJsonString, fromJson, Chunk operationsCall it directly, or ZIO.succeedCall it directly, or IO.pure
Returns an EitherfromJson, a decode with any format codecZIO.fromEitherIO.fromEither
Blocks a threadSQL queries, Stream#runCollect on the JVMZIO.attemptBlockingIO.blocking
Owns a resourceA Resource from ScopeWrap it in ZIO.acquireReleaseWrap it in Resource.make
Runs asynchronouslyAn Async valueBridge it with ZIO.asyncInterruptBridge it with IO.async
Produces a streamA ZIO Blocks StreamTurn it into a ZStreamTurn it into an fs2 Stream

ZIO has library help for one case: the sql-zio module returns ZIO effects that already run on the blocking pool and provides the database as a ZLayer (How to Use the sql Module from a ZIO Application). Every other bridge is a few lines of your own code, and the full guide gives you those lines for both effect systems.

Why It Works This Way​

Because a block does its work when you call it, it cannot know whether the calling thread may block, or how your effect system cancels work. Keeping that decision in your code means the same block works in ZIO, cats-effect, Kyo, Ox, Akka or a plain main method, and you never adapt your application to a runtime that ZIO Blocks would otherwise bring along.

Learn More​

How to Use ZIO Blocks in a ZIO or cats-effect Application builds a small orders service that covers every row of the table, with cancellation and cleanup tested in both effect systems. If you are moving an existing code base, the migration guides map common Scala libraries to their ZIO Blocks counterparts. Finally, Where Next suggests what to read after this section.