Open-source project
socketry/nio4r avatar
socketry/nio4r

nio4r: cross-platform asynchronous I/O selectors for Ruby

Cross-platform asynchronous I/O primitives for scalable network clients and servers.

993 stars93 forksCNOASSERTION

At a glance

What is it?
nio4r is the small substrate that Ruby event libraries are built on. It gives you selectors that watch many IO objects for readiness, monitors that control what a specific object is interested in, and native byte buffers, with a libev extension for CRuby, a Java NIO extension for JRuby and a pure Ruby fallback for everything else. The projects above it include Puma, ActionCable and Celluloid.
Who is it for?
nio4r fits a library author who is writing an event-driven Ruby library and wants one selector API that behaves the same on CRuby, JRuby and TruffleRuby, without shipping a full reactor of their own. It does not fit an application team, because it is deliberately not a framework, and it does not fit a project that has just moved to a Ruby version the README does not list.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The layer underneath the event libraries

nio4r is a Ruby gem that provides an abstract, cross-platform, stateful I/O selector API, and the README explains the term in the first paragraph, since selectors are the heart of reactor based event loops and monitor multiple I/O objects for various kinds of readiness, such as being ready to read or to write. It is modelled on the Java NIO API, with the deliberate simplification that the API is smaller. The reason a Ruby project would care is portability, because a reactor has to work on the operating system the game runs on and on the Ruby the host ships, and the projects that use the gem make the case for it. ActionCable, the Rails 5 WebSocket protocol, uses it for its WebSocket server. Celluloid, the actor based concurrency framework, uses it for asynchronous I/O. Async, the framework from the same author as nio4r, is built on it, and so is Puma, the concurrency focused Ruby web server.

The three components you actually call

The wiki splits the library into three pages, and the split matches the three things a reactor needs. A selector is the object that monitors many IO objects at once for readiness events, and it is the piece that owns the event loop. A monitor is bound to one IO object and controls what that object is interested in, so you can ask for read interest, write interest or both, and then inspect the readiness the selector reports for it. A byte buffer is a fixed-size native buffer for high performance I/O, which is the part that avoids allocating a Ruby string per read and is therefore the reason a native extension exists at all. The API is deliberately minimal, and the stated goals are worth quoting in spirit: expose high-level interfaces for stateful IO selectors, keep the API small to maximise both portability and performance across operating systems and Ruby implementations, and provide inherently thread-safe facilities for working with IO objects.

Three backends, one API

The backend story is what makes the gem portable, and the README names three. The libev backend is a CRuby C extension that targets multiple native selector APIs, with epoll and kqueue given as the examples, so a single extension covers the selector mechanisms of the different Unix flavours and Windows. The Java NIO backend is a JRuby extension that wraps the Java NIO subsystem, so the same Ruby code runs on the JVM with the platform's own selector underneath. The pure Ruby backend is based on the kernel select call and is described as something that should work on any Ruby interpreter, which makes it the universal fallback and the reason the gem can be installed anywhere. The trade is performance, and it is inherent rather than a mistake. A select based loop has to ask the operating system about every object on every pass, while a native extension can wait on many objects at once, so the portable path is the slow path and the fast path is the one that needs a compiler.

The explicit non-goal, and why it is a good one

The README has a section on non-goals, and stating them is one of the reasons to trust the project. nio4r is not a full-featured event framework like EventMachine or Cool.io. Instead it is the sort of thing you might write a library like that on top of, and it provides a minimal API so that individual Ruby implementers can produce optimised versions for their platform without maintaining a large codebase. That is a different product from a reactor, and it comes with a different cost. If you want to write a library that needs a selector, nio4r is the smallest thing that will do the job and it will behave identically on the three Ruby implementations, which is exactly what a library that supports several of them needs. If you want to write an application with timers, work queues, concurrency primitives and a scheduler, nio4r is the wrong shape of dependency, because you would be rebuilding all of that on top of a selector.

Releasing, and the two runtimes

The release instructions are short and separate the two build targets, which is the part most people would otherwise have to work out themselves. The version is bumped first, with a bake task, and then for CRuby the sequence is a clean followed by a release, both through rake. For JRuby there is more to do, because the Java extension has to be compiled and the environment has to match. The README notes that the lock file may need deleting before the bundle install, that the correct JDK has to be installed and selected, showing the Arch package and the tool that sets the active Java version, and that the interpreter has to be switched with a version manager, after which the bundle is updated and the gem is compiled and released. The repository carries a release certificate file and a releases document alongside the gem specification and the Rakefile, so the signing and the changelog are part of the process rather than an afterthought.

Where it stands, and how a team should choose

Two facts about the project deserve a reader's attention. The supported Ruby list in the README runs from 2.5 to 3.0, with JRuby and TruffleRuby listed separately, which dates the documentation, and the last published release is from March 2024 even though the branch was pushed in October 2026, so the gem on the package index is old relative to the working tree. The second fact is about positioning rather than time. A substrate ages differently from a framework, because the frameworks built on it keep changing while the interface between them stays stable, so a gem like this can be quiet for years and still be exactly right. The choice for a team is between three approaches: writing the reactor yourself in pure Ruby for maximum portability and minimum speed, taking on a full event framework such as EventMachine or Cool.io and its larger API and its own history, or using nio4r as a small, well-tested substrate and building only what your library actually needs on top of it.

Editorial conclusion

nio4r fits a library author who is writing an event-driven Ruby library and wants one selector API that behaves the same on CRuby, JRuby and TruffleRuby, without shipping a full reactor of their own. It does not fit an application team, because it is deliberately not a framework, and it does not fit a project that has just moved to a Ruby version the README does not list. Before adopting it, check the supported Ruby list against your runtime, because the versions the README names end at 3.0 while the branch is still being touched, and prefer a framework such as Async if you want a reactor rather than a substrate, since building an event loop on a minimal primitive is a project in itself.

Frequently asked questions

What is nio4r?

It is a Ruby gem that provides a small, cross-platform, stateful I/O selector API for asynchronous network clients and servers, modelled on the Java NIO API but simplified, with a C extension for CRuby, a Java extension for JRuby and a pure Ruby fallback.

Which projects use nio4r?

ActionCable, the Rails WebSocket protocol, uses it for its WebSocket server, Celluloid uses it for asynchronous I/O, the Async framework is built on it, and the Puma web server uses it as well.

What backends does nio4r support?

Three: a libev based C extension for CRuby that targets native selector APIs such as epoll and kqueue, a Java NIO extension for JRuby, and a pure Ruby backend based on the kernel select call that works on any Ruby interpreter.

What are the main components of nio4r?

Selectors, which monitor many IO objects for readiness events, Monitors, which control the interests of a specific IO object and let you inspect its readiness, and Byte Buffers, which are fixed-size native buffers for high performance I/O.

Is nio4r a full event framework?

No. The README states that it is not a full-featured event framework like EventMachine or Cool.io, and describes it instead as the sort of thing you might write such a library on top of, with a minimal API so implementers can optimise per platform.

Which Ruby implementations does nio4r support?

Ruby 2.5, 2.6, 2.7 and 3.0, plus JRuby and TruffleRuby, and the release process in the README is split into separate steps for the CRuby and the JRuby builds.

Official sources

  1. Issues
  2. README
  3. Releases
  4. socketry/nio4r on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/socketry-nio4r.svg)](https://hysenlabs.com/projects/socketry-nio4r)

Was this useful?