Open-source project
socketry/falcon avatar
socketry/falcon

Falcon's changelog shows four patch releases fixing one leaked counter

A high-performance web server for Ruby, supporting HTTP/1, HTTP/2 and TLS.

3,054 stars105 forksRubyMIT

At a glance

What is it?
Falcon is a multi-process, multi-fiber rack-compatible HTTP server built on the author's own async libraries, and it grew out of a performance experiment until it replaced the author's own production stack. What its page gives you instead of a feature list is a detailed changelog, and the pattern in that changelog is more informative than the numbers would have been.
Who is it for?
Falcon suits a Ruby service that wants HTTP/2 without giving up a rack-compatible interface, and that would rather run its own web server than sit behind a separate application server. Three things to check before you deploy it.
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 7 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • socketry/falcon3,054 ★ · +13
Star history
Repository2026-09-242026-11-14
socketry/falcon3k3.1k

13 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

It started as a benchmark and replaced the author's own production stack

The motivation section is written in the first person and it is a story about experiments rather than a plan.

The author was building an async library and saw an opportunity to build an HTTP client and server component on top of it. After experimenting with that, he decided to build an actual web server, and the stated reason is to compare and validate performance, primarily out of interest.

Falcon then grew out of those experiments into something with a second purpose: it permitted testing existing real-world code on top of the async library. That is the point at which it stopped being a benchmark.

The third stage is the one with numbers attached. Once it worked, the author replaced a production stack of Nginx with Passenger, and a development stack of Puma, with Falcon. The reasons given are that it simplifies deployment and that it helps minimise environment-specific bugs, which is a bug class that comes from having three different servers between your laptop and production.

That is the most useful sentence on the page for an adopter. The library was validated on somebody else's real application before anybody else was asked to try it, and the person who wrote it runs it in production.

One counter, four patch releases

The release notes on the page are detailed enough to show a pattern, and the pattern is a metric leak being closed one edge at a time.

The minor release added support for utilisation metrics, which is when the counter appears. Then four patch releases in a row deal with it. The first makes sure the counter is decremented after the response body is closed, including the callbacks that run when a rack response finishes. The second makes sure it is decremented in the server call path when either the parent implementation or the request-finished wrapper raises, and it says explicitly that this is so utilisation metrics are not leaked on error paths. The third makes sure it is decremented if closing the response body itself raises. The fourth is unrelated and strips a proxy authorisation header in the proxy middleware.

So between one minor and one patch, the same invariant was fixed three times, each time for a different way an exception could escape. That is not sloppiness so much as a symptom of a counter that has to be decremented on every exit path from a block with several of them.

It is also a good advertisement for reading a changelog instead of a version number. Four of the six recent releases are about one metric, and none of them is about performance.

The 0.55.0 release renamed a dependency and dropped the legacy path

One release in the visible history is marked with three breaking changes, and they are all about naming and configuration rather than behaviour.

The first drops the dependency on a supervisor component whose name says container, and tells you to migrate to the component whose name says service instead.

The second removes support for legacy environments, including the framework's own configuration class, with the instruction to use the new configuration class from the async library directly.

The third removes a task that restarted the supervisor, saying it is superseded by the equivalent task under the async namespace.

Two observations follow. The first and third are the same change seen from two ends, which is what a dependency rename looks like when the project that provides it also owns the tooling around it. And the second is the one that will bite: a configuration class removed in favour of using another library's class directly is a source-level change, so an application pinned to the older line needs edits rather than a version bump.

The patch release immediately before it, in the previous minor, had already fixed handling of old style supervisors, which suggests the rename was prepared for over more than one release.

Ten guides, two of which are about operating the server

The usage section is a list of ten guides, each with a sentence describing it, and the list is the closest thing the page has to a feature list.

Three are about running Ruby applications: an overview of using the server for Ruby web applications, one on hosting Rails applications with it, and one on deployment that covers the recommended methods, configuration options and worked examples for different environments, naming systemd and Kubernetes among them.

One is about scaling out: a guide to running workers with independently bound endpoints, publishing them dynamically over xDS, and balancing requests according to their current load using ORCA. That is a service-mesh vocabulary, and it is also the release that added the cluster classes.

The rest are capability and reference: performance tuning, WebSockets, interim responses for sending early hints to the client, and an overview of how an incoming request is handled.

The distribution is telling. Four of the ten are about deployment and operation rather than about writing Ruby, which matches the project's stated ambition of trivialising server deployment, and matches the fact that the author's own motivation was replacing two other servers.

Business support sits between the design goals and the documentation

After the long term vision and before the usage guides, the page sells support.

The vision paragraph is worth reading first, because it is the most expansive claim on the page. The long term goal is a web application platform that trivialises server deployment, where an application fully describes all of its components: HTTP servers, databases, periodic jobs, background jobs and remote management. The argument is that today those facets are commonly handled independently in platform specific ways, which makes new instances and infrastructure changes harder than they should be.

Then the support offer. Direct support by chat and email, advance notification of bugs and security issues, priority consideration of feature requests and bug reports, and better software by funding development and testing. Registration happens on the vendor's commercial site rather than in the repository.

Placing a commercial offer in the middle of the page is a choice. It also tells you something true about the project: it is one maintainer's work, funded partly by support contracts, which is the usual shape for infrastructure that has to be dependable in production.

Contributing is five commands and a certificate

The contribution section is a numbered list with the literal commands in it, which is either welcoming or slightly old fashioned depending on your taste.

Fork the repository. Create a feature branch with a checkout and a branch name. Commit the changes with an add and a message. Push the branch. Open a pull request. Five steps, no mention of rebasing, conventional commits or a changelog entry.

Testing and releasing each get one line, and both go through a bundled task runner rather than a bare command. The test suite is one command invoking a specific framework, and a release is one command with a patch, minor or major argument:

shell
bundle exec sus
shell
bundle exec bake gem:release:patch # or minor or major

Then the requirement that is unusual and worth noticing: every contributor must comply with the Developer Certificate of Origin, and the stated reason is to protect users by ensuring contributions are properly licensed and attributed. That is a stronger guarantee than a licence file alone, because it asserts something about each individual commit.

The community guidelines paragraph at the end is cut off partway through a word, so the page does not finish its own code of conduct.

Two changelogs, a committed certificate, and a linter config for a hosted service

The root of the repository explains how the project is put together, and a few entries are worth naming.

There are two changelogs. The readme carries a releases section with per-version entries written out in full, and there is a separate changes file at the root. For a project whose page is already detailed, that is duplication with a drift risk, and the readme version is the one a reader sees.

There is a release certificate file committed at the root, alongside the gem specification, the gem dependency file and the build script. Committing a certificate is normal for a signed release, and it is the kind of file a contributor should not be surprised by.

There are two linting configurations: one for the project itself, and one for a hosted code quality service. Having both is normal, and the hosted one is the file that will be read first by anyone scanning a dependency.

Also at the root: a mailmap so that commit authors are attributed consistently, a project metadata file for a third-party command line tool, a fixtures directory for tests, a directory of vendored gems, a guides directory that is the source of the documentation site, and a bin directory for the executables the gem installs.

Twenty-five examples, and one of them is not Ruby

The examples directory has twenty-five entries, and reading the names is the fastest way to understand what the server is actually used for.

There are the obvious ones: a hello world, an echo server, a server showing headers, a cookies example, one demonstrating a pushback stream, and one that pushes. There are integration examples against real systems: a relational ORM, an in-memory data store, an interface definition compiler example, and a multi-protocol example. There are examples that exist to prove a property rather than to demonstrate an API: a benchmark, a memory-constrained example, a rate-limited one, one that sleeps, and one that reaches the internet.

There are deployment examples too: a cluster example matching the guide about dynamic workers, a proxy example, and one named after the supervisor service that the 0.55.0 release renamed a dependency to.

And there is a hello example written for another language entirely, which is the one that stands out. A multi-fiber rack-compatible server that will run code written in a different runtime is making a claim about the interface rather than about the implementation, and shipping an example that proves it is the cheapest way to make that claim checkable.

Editorial conclusion

Falcon suits a Ruby service that wants HTTP/2 without giving up a rack-compatible interface, and that would rather run its own web server than sit behind a separate application server. Three things to check before you deploy it. Read the breaking release in the middle of the recent history, because it renamed a dependency and removed the legacy configuration path, and a version that predates it is not a drop-in. Read the performance guide rather than the marketing, since the design rests on fibers per request and a blocking request only costs its own fiber. And note that the project is commercially supported, which is a reasonable thing to buy with a server that sits in front of your application, and a reasonable thing to check the terms of before you rely on it.

Frequently asked questions

What is Falcon?

It is a multi-process, multi-fiber HTTP server that is compatible with rack applications, built on the author's async, container and HTTP libraries. Each request runs in a lightweight fiber and can block on an upstream request without stalling the whole server process, and HTTP/1 and HTTP/2 are supported natively.

What did Falcon replace in the author's own setup?

Nginx with Passenger in production and Puma in development, with the stated reasons being simpler deployment and fewer environment-specific bugs. Before that it was built to compare and validate the performance of an async HTTP library, and then used to run real applications on top of it.

What changed in the breaking Falcon release 0.55.0?

Three things. The dependency on a supervisor component named for containers was dropped in favour of the one named for services, support for legacy environments including the framework's own configuration class was removed in favour of using the async library's configuration class directly, and the supervisor restart task was removed as superseded.

How do I run the Falcon test suite and cut a release?

Both go through a bundled task runner. The test suite is one command invoking the project's test framework, and a release is one command with a patch, minor or major argument that drives the gem release task.

Does Falcon support Rails and Kubernetes deployments?

There are separate guides for hosting Rails applications and for deployment, where the deployment guide covers the recommended methods, configuration options and worked examples for different environments, naming systemd and Kubernetes among them. A third guide covers running workers with independently bound endpoints, published dynamically over xDS and balanced by current load.

What HTTP features beyond HTTP/1 and HTTP/2 does Falcon cover?

The description names TLS, and the guides cover WebSockets and interim responses for sending early hints to the client, plus performance tuning and an overview of how an incoming request is handled. The page describes Falcon as rack-compatible rather than tied to a particular application server.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. socketry/falcon 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-falcon.svg)](https://hysenlabs.com/projects/socketry-falcon)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/socketry-falcon.svg)](https://hysenlabs.com/projects/socketry-falcon)

Was this useful?