Open-source project
ohler55/agoo avatar
ohler55/agoo

agoo is a C-backed HTTP server that speaks Rack and GraphQL

A High Performance HTTP Server for Ruby

933 stars39 forksCMIT

At a glance

What is it?
Agoo is a Ruby HTTP server whose core is a C extension, built to serve static files and dispatch requests into Rack handlers, with a built-in GraphQL module and support for WebSockets and SSE. Its README is emphatic about the speed claims, and equally emphatic that the server is not available on Windows.
Who is it for?
agoo fits a Ruby team that serves static assets heavily, wants GraphQL without bolting on a separate server, and can run on Unix-like systems. It is the wrong choice on Windows, which the README rules out, and the wrong choice for an application that keeps state in process, because clustered mode requires stateless workers.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 167 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 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The request path runs through a C extension, not through Ruby

Agoo is a high performance HTTP server for Ruby. The repository is written in C, with the Ruby side living in ext/ and lib/, and the gem exposes a small procedural API for binding a socket, registering handlers and starting the loop.

The API shape is the first clue about the design. There is no rackup file in the basic example and no middleware stack to assemble. You initialise the server with a port and a document root, register a handler for a method and path, and start it.

ruby
require 'agoo'

Agoo::Server.init(6464, './root')

class MyHandler
  def call(req)
    [ 200, { }, [ "hello world" ] ]
  end
end

handler = MyHandler.new
Agoo::Server.handle(:GET, "/hello", handler)
Agoo::Server.start()

The handler returns the Rack triple, a status, a header hash and a body array, so the dispatch contract is the Ruby rack API. That is what makes Agoo usable with Hanami and Rails, as the README states, and what allows it to sit behind the same application code you already have.

The performance claim in the README comes with a benchmark link rather than a methodology, so treat it as the project's own figure rather than an independent measurement. What is notable is that the same document claims both throughput and latency improvements, and separately notes that latency was not at the top of a particular benchmark table until a later release addressed it.

GraphQL is a module inside the server, not a middleware you add

The GraphQL support is part of Agoo rather than an add-on, which changes how you structure the server. The README's example defines the schema in plain Ruby classes, passes the schema to Agoo::GraphQL.schema, and then loads the GraphQL type definitions with a dedicated load call.

ruby
Agoo::Server.init(6464, './root', thread_count: 1, graphql: '/graphql')
Agoo::Server.start()
Agoo::GraphQL.schema(Schema.new) {
  Agoo::GraphQL.load(%^type Query { hello: String }^)
}
sleep

The graphql option in init points the server at the path that serves GraphQL, and thread_count sets how many threads handle requests. The %^...^ delimiters around the type definition are Agoo's own marker syntax rather than a heredoc, which is how the type is handed to the loader inside the schema block.

Version 2.11.0 added support for GraphQL subscriptions, according to the news section, and the README notes that a PR was submitted to update the rack spec for WebSocket and SSE support. The example directory contains a graphql folder with hello.rb and song.rb, and the misc directory holds documented walkthroughs including flymd for realtime push, glue for publish and subscribe, optimize for static asset use, push with Rack, rails, and song described as a fun and simple GraphQL example.

Installing for plain Rack or for Rails

Installation is a gem install, and the README is explicit that Agoo supports rack compatible apps.

bash
gem install agoo

For a Rails application the gem goes into the Gemfile.

bash
# Gemfile
gem 'agoo'

Then the bundle is installed and the server is started with agoo as the handler.

bash
$ bundle install
bash
$ rails server -u agoo

The -u flag is the part worth remembering, since it replaces the default Rack server for that run. The README also points at a separate project, WABuR, which has an option to use Agoo, and Perfer, listed as a separate repository of the same author.

Two boundaries show up immediately in the docs. Agoo is not available on Windows, which the README states in one line. And clustered Agoo, described in the news section as ready, only helps when the application is stateless: the README is explicit that no data may be shared between workers. That is a hard constraint on application design, not a tuning knob.

Clustering pays off only when the application shares nothing

The clustered mode is the part of Agoo that most often gets misread. The README says that for a slower application on a machine with multiple cores a significant performance improvement is realized, and immediately follows it with the condition that the application must be stateless in that no data is shared between workers.

That condition is the design, not a caveat. If your application keeps a session in a process-local hash, an in-memory cache, or a connection to a local socket, then clustering it gives you workers with inconsistent state, and you are debugging a class of bug that only appears under load.

The repo also carries the topics of clustering and clusters, and the presence of an example directory with files named multi.rb and mem.rb suggests both multi-process and shared-memory configurations are exercised somewhere in the codebase. The README does not walk through the cluster configuration in detail, and the documentation link points to the gem documentation rather than a clustering chapter, so the practical route for a clustered setup is to read the CHANGELOG and the example directory rather than to expect a tutorial.

The speed story and the caveat it comes with

The README makes performance claims in the aggressive register typical of server benchmarks, and it links to the web-frameworks benchmark results rather than publishing a methodology. It describes serving static resources at hundreds of thousands of fetches per second, and states that a simple hello world Ruby handler reaches over 100,000 requests per second on a desktop computer, placing it at about 85 times faster than Sinatra and 1000 times faster than Rails with latency two orders of magnitude lower or more.

A separate claim in the news section says Agoo serves Rails static assets more than 8000 times faster than the default Puma.

Two things are worth saying about these numbers. They are the maintainer's own figures, published in the README, and the benchmark link is the appropriate place to judge them. And they are all about static assets and hello world handlers, which are the cases a C extension helps most. A number like that says little about an application dominated by database queries or object allocation, which is the case where the Ruby side of the work still dominates.

For a team, the useful conclusion is narrower than the marketing: if your bottleneck is serving files, the difference can be large, and if your bottleneck is your application code, changing servers will not move the number much.

Two branches, and a release process that explains them

The repository layout is small and worth reading as documentation. At the top level there is ext/ for the C extension, lib/ for the Ruby side, example/ with a directory per feature such as ssl, tls, upload, push, middleware and graphql, misc/ holding the documented walkthroughs in markdown, and a test/ directory. There is also a notes file and a tea.yaml.

The branching model is stated plainly in the README. Releases are made from the master branch, the default branch for checkout is develop, and pull requests should be made against develop. If you are reading the repository through a browser link that points at the default branch, you are looking at develop and not at a released state.

On maintenance, the last push to the repository was on 2026-05-09, and the two most recent releases are v2.15.15 from that date and v2.15.14 from 2025-09-24. The licence is MIT, so the gem can be used in commercial applications, and security fixes are handled through a Tidelift subscription for the gem, which the README lists as the supported path.

There is a SECURITY.md in the repository root and a CHANGELOG.md referenced for the release history, so the version-specific details live there rather than in the README.

Editorial conclusion

agoo fits a Ruby team that serves static assets heavily, wants GraphQL without bolting on a separate server, and can run on Unix-like systems. It is the wrong choice on Windows, which the README rules out, and the wrong choice for an application that keeps state in process, because clustered mode requires stateless workers. Verify first that your app holds no shared data between workers, then read the CHANGELOG.md before upgrading, since the last push to the repository was on 2026-05-09 and releases are cut from the master branch rather than the develop branch you check out by default.

Frequently asked questions

How do I install and run agoo?

Install the gem with gem install agoo. For a Rack application, call Agoo::Server.init with a port and document root, register a handler with Agoo::Server.handle, and call Agoo::Server.start. For Rails, add gem 'agoo' to the Gemfile, run bundle install and start the server with rails server -u agoo.

Does agoo work on Windows?

No. The README states that Agoo is not available on Windows. It is built as a C extension for Ruby, so it targets Unix-like environments.

What are the requirements for using agoo in clustered mode?

The application must be stateless, with no data shared between workers, as the README states. Clustering is described as giving a significant improvement for a slower application on a machine with multiple cores.

Does agoo support GraphQL and WebSockets?

Yes. The GraphQL module is built in, with Agoo::Server.init taking a graphql option for the path and Agoo::GraphQL.schema plus Agoo::GraphQL.load registering the schema. WebSockets and SSE are supported, and version 2.11.0 added GraphQL subscriptions.

Which branch should I pull requests against in agoo?

Pull requests should be made against the develop branch, which is also the default branch for checkout. Releases are cut from the master branch, so the code you see on the default branch is ahead of the last release.

Official sources

  1. Issues
  2. License: MIT
  3. ohler55/agoo on GitHub
  4. README
  5. Releases
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/ohler55-agoo.svg)](https://hysenlabs.com/projects/ohler55-agoo)

Was this useful?