Skip to content

Instantly share code, notes, and snippets.

@sam-saffron-jarvis
Created July 23, 2026 00:50
Show Gist options
  • Select an option

  • Save sam-saffron-jarvis/e13e8138bdb31385a6671e59ef58824a to your computer and use it in GitHub Desktop.

Select an option

Save sam-saffron-jarvis/e13e8138bdb31385a6671e59ef58824a to your computer and use it in GitHub Desktop.
Iodine vs Agoo as a Ruby micro web server dependency (July 2026)

Iodine vs Agoo as a Ruby micro web server dependency

Assessment date: 23 July 2026

Conclusion

Agoo is the better-shaped dependency, but I would not ship either current release. If forced to choose between the projects, I would use iodine's released 0.7 line with the current load regression patched and additional parser-focused tests.

Agoo is materially smaller, has better test coverage signals, and is more focused. Unfortunately, its current release has a remotely triggerable request-parsing crash that I reproduced locally. Iodine has broader contributor history and active development, but its current release is broken on Ruby versions below 4.0 and its upcoming 0.8 line is a very large, API-breaking rewrite.

Comparison

iodine 0.7.59 agoo 2.15.15
Gem size 675 KB 166 KB
Unpacked source 2.13 MB 747 KB
Installed footprint in a local x86-64 Linux/Ruby 3.4 build 4.40 MB 1.67 MB
Native core ~48,900 lines ~22,800 lines
Test code ~321 lines ~2,323 lines
Runtime gem dependencies None None
Project started 2015 2017
Commits in the last year on the released/default line 6 5
Commits in the last two years 12 12
RubyGems owners 1 1
Maintainer picture Boaz Segev, with substantial historical work from Jan Biedermann Almost entirely Peter Ohler
Latest release 0.7.59, 23 May 2026 2.15.15, 9 May 2026
Latest relevant CI Released branch failed; workflow primarily builds rather than running tests Passed, including tests

The size and line-count measurements above were taken directly from the current gem packages and checked-out repositories. They are useful maintenance proxies, not formal measures of runtime memory or cyclomatic complexity.

Weight and code complexity

Agoo

Agoo is substantially lighter:

  • Its gem is roughly one quarter the size of iodine's.
  • Its installed footprint was about 38% of iodine's in the same local build environment.
  • It has less than half as much native core code.
  • Its test suite is considerably larger despite the smaller implementation.

Its scope is mostly HTTP/Rack, static files, WebSockets, SSE, TLS, clustering and GraphQL. GraphQL adds non-trivial surface area that a minimal server may not need, but the overall implementation is still considerably more focused than iodine.

Iodine

Iodine is closer to an application-server platform than a minimal HTTP adapter. It includes or integrates:

  • HTTP and static-file serving
  • WebSockets and SSE
  • in-process and Redis-backed pub/sub
  • custom TCP protocols
  • process workers and thread pools
  • clustering and hot restart machinery
  • TLS
  • JSON and Mustache functionality
  • the underlying facil.io evented C framework

That broader feature set explains some of its size, but it also means more native parsing, concurrency, memory-management and protocol code to audit. Iodine additionally documents that Rack response streaming is not supported in the normal streaming sense: body.each blocks the iodine thread and data is not sent until iteration finishes.

History, activity and maintainers

Both projects have a bus factor of approximately one.

Iodine

  • Repository created in October 2015.
  • RubyGems has one owner.
  • The commit history has roughly 1,900 commits attributable to Boaz Segev under several identities, 94 from Jan Biedermann and 24 from Ian Ker-Seymer. Most other contributors are very small.
  • The released/default branch had 6 commits in the last year and 12 in the last two years.
  • Current development is concentrated on the rw8.0 branch. That branch was actively changing as recently as 22 July 2026.

Iodine therefore has somewhat better historical contributor depth than Agoo, but it is still maintainer-led rather than team-maintained.

Agoo

  • Repository created in December 2017.
  • RubyGems has one owner.
  • Peter Ohler has 307 recorded commits; the next contributors have only two each.
  • The default/release lines had 5 commits in the last year and 12 in the last two years.
  • Releases are sparse but generally documented and deliberate.

Agoo has the cleaner and smaller implementation, but the maintainer concentration is more extreme.

Current release blockers

Agoo 2.15.15: reproducible request-parsing crash

Agoo issue #139, opened on 9 March 2026, reports an integer overflow in HTTP request-body length handling leading to a heap-buffer overflow.

Inspection of the 2.15.15 source shows the risky arithmetic remains in ext/agoo/con.c: an unbounded parsed content length is added to the header length before allocating and copying the request.

I tested the reported condition locally against the released Agoo 2.15.15 on Ruby 3.4/x86-64 Linux. A single malformed local HTTP request caused the server process to terminate with a segmentation fault and exit status 139.

Agoo 2.15.15 was released two months after the report and fixed a separate connection-header overflow and path-handling issues, but it did not fix this content-length overflow. The issue remains open without a maintainer response.

For a network-facing HTTP parser implemented in C, this is disqualifying until patched.

Iodine 0.7.59: broken on Ruby below 4.0

Iodine issue #167 documents a regression in version 0.7.59 that prevents require "iodine" on Ruby versions below 4.0.

The release changed an internal IodineObjectStorage object from a Ruby Class to a Module, then passed it to a C API that requires a class. The reported failure was verified on Ruby 2.6 through 3.4. The proposed repair is a small source change, but no fixed gem has been released.

Other concerning release-process signals:

  • 0.7.59's changelog does not describe the release.
  • The latest CI run on the released master branch failed.
  • The master workflow mostly compiles/installs iodine; its test invocation is commented out.
  • The released line has only about 321 lines of checked-in test code around roughly 49,000 lines of native core.

The current iodine gem is therefore not a sensible unmodified dependency for mainstream Ruby 3.x applications.

Iodine 0.8 does not yet solve the dependency question

Iodine's active rw8.0 branch identifies itself as 0.8.0.rc.02 and describes itself as a total rewrite with an API that should be considered changed or broken.

It is also much larger than the released line:

  • approximately 137,000 lines of native extension code;
  • around 3,825 lines of checked-in tests;
  • 185 files changed relative to the old line, with roughly 172,000 insertions and 54,000 deletions at the inspected point.

The branch is genuinely active and has more modern CI, but an active release candidate rewrite is not the same thing as a stable dependency. Its enormous increase in native scope cuts directly against the goal of a small, easily maintained web server.

Recommendation

  1. Do not use stock Agoo 2.15.15 while the reproducible request-parsing crash remains.
  2. Do not use stock Iodine 0.7.59 on Ruby 3.x; its load-time regression needs patching first.
  3. If constrained to these two projects, prefer Iodine's released 0.7 line with the load regression patched, parser-focused regression tests added, and TLS terminated at a reverse proxy.
  4. Do not adopt iodine's rw8.0 rewrite merely because it is more active. Wait for a stable release and perform a fresh API, size, parser-safety and compatibility assessment.
  5. For a genuinely minimal server, reconsider whether either broad, single-maintainer native-C implementation is the right dependency. Build size is not the main risk; ownership of a network-facing memory-unsafe parser is.

Primary sources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment