Rackless Ruby Servers: Why not?

An exploration of the interaction between four different Ruby web servers and their respective Rack handlers

Luis Vasconcellos
2 min readFeb 9, 2019

The idea is to use these servers to GET a Hello, World! at /, both on and off Rack. The goal is to make it clearer why Rack was created in the first place, and why to this day it’s still so relevant.

Getting Ready

The examples to come will help to illustrate the role that Rack, specially the Rack::Handler, plays on being that minimal interface between Ruby web servers and Ruby web frameworks, as stated by Rack documentation.

To run each one of the examples in this article:

$ ruby server.rb

To verify that example works as expected:

$ curl localhost:3000

Which should output a simple:

> Hello, World!


Off Rack

Since Webrick comes with Ruby, one can directly require, mount and run the server, without needing to install any third party libraries:

a ‘Hello, World!’ with Webrick and nothing else, in a single file

On Rack

On Rack, using its famous minimal interface, the same behaviour could be achieved with:

a ‘Hello, World!’ with Webrick on Rack, in a single file


Off Rack

Mongrel, Thin and Puma will require a gem installation. For sake of simplicity, in this article each gem will be installed using an embedded Gemfile definition. So the Mongrel example would look like this:

a ‘Hello, World!’ with Mongrel and nothing else, in a single file

On Rack

On Rack it will be necessary to use a specific rack version, since Mongrel support was removed on one of Rack's last releases, but otherwise the interface remains the same:

a ‘Hello, World!’ with Mongrel on Rack, in a single file


Thin and Puma examples are going to be a bit closer to the Rack specification even for a simpleHello, World!, which was actually a bit surprising to be honest.

That is because, different from the previously shown Webrick and Mongrel, they both expect an object with a Rack app interface, even when directly launched without their respective Rack handlers.

Off Rack

Thin is definitely the one that requires the least amount of code to launch the simple Hello, World! output. This how one can achieve it:

a ‘Hello, World!’ with Thin and nothing else, in a single file

On Rack

On Rack, the interface remains the same from the previous examples:

a ‘Hello, World!’ with Thin on Rack, in a single file


Off Rack

This is how a Hello, World! with Puma could be achieved:

a ‘Hello, World!’ with Puma and nothing else, in a single file

On Rack

In Puma case, the rack gem doesn't come with the Rack::Handler::Puma class, as one would expect, since puma comes with its own rack handler.

And as expected, once again, the interface remains the same:

a ‘Hello, World!’ with Puma on Rack, in a single file

That’s it! Have anything to say? Leave a comment, I’d love to hear about it. Learned something new? Share this article and spread the word!