Skip to main content
Version: ZIO 2.x


ZIO NIO is a small, unopinionated ZIO interface to NIO.


In Java, there are two packages for I/O operations:

  1. Java IO (

    • Standard Java IO API
    • Introduced since Java 1.0
    • Stream-based API
    • Blocking I/O operation
  2. Java NIO (java.nio)

    • Introduced since Java 1.4
    • NIO means New IO, an alternative to the standard Java IO API
    • It can operate in a non-blocking mode if possible
    • Buffer-based API

The Java NIO is an alternative to the Java IO API. Because it supports non-blocking IO, it can be more performant in concurrent environments like web services.


ZIO NIO is a ZIO wrapper on Java NIO. It comes in two flavors:

  • zio.nio.core — a small and unopionanted ZIO interface to NIO that just wraps NIO API in ZIO effects,
  • zio.nio — an opinionated interface with deeper ZIO integration that provides more type and resource safety.

In order to use this library, we need to add one of the following lines in our build.sbt file:

libraryDependencies += "dev.zio" %% "zio-nio-core" % "1.0.0-RC11"
libraryDependencies += "dev.zio" %% "zio-nio" % "1.0.0-RC11"


Let's try writing a simple server using zio-nio module:

import zio._
import zio.console._
import zio.nio.channels._
import zio.nio.core._

object ZIONIOServerExample extends zio.App {
val myApp =
.use(socket =>
for {
addr <- InetSocketAddress.hostName("localhost", 8080)
_ <- socket.bindTo(addr)
_ <- putStrLn(s"Waiting for incoming connections on $addr endpoint").orDie
_ <- ZStream
.mapMPar(16) {
_.use { case (closeConn, channel) =>
for {
_ <- putStrLn("Received connection").orDie
data <- ZStream
.run(Sink.foldLeft("")(_ + _))
_ <- closeConn
_ <- putStrLn(s"Request Received:\n${data.mkString}").orDie
} yield ()
} yield ()

override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] =

Now we can send our requests to the server using curl command:

curl -X POST localhost:8080 -d "Hello, ZIO NIO!"