Last year, 37signals released two HTTP proxies: Thruster and Kamal-proxy. Looking at the feature list for both, you might find yourself scratching your head, wondering about the differences.
The feature lists overlap quite a lot:
- Both are HTTP proxies.
- Both support HTTP/2.
- Both are written in Go.
- Both handle automatic TLS.
- Both provide protection against long requests and slow clients.
So, which one should you use? To make an informed decision, it helps to understand why they were created in the first place.
Thruster
Thruster doesn’t try to compete with more general proxies like NGINX or Apache. It “wraps” around your application process and can only handle one process, which means:
- Thruster can only serve one app (no routing to multiple apps based on URL).
- Thruster can only serve one instance of this app (no load balancing).
- Thruster and the app server must run on the same machine/container.
- Restarting or updating your application will cause downtime.
Thruster was created by 37signals to serve Once apps. They needed something lightweight in front of the Rails app server to handle things like:
- HTTP/2
- SSL/TLS
- HTTP caching
- Responding with assets/files without blocking the app server (x-sendfile header)
- Long requests/slow client protection
Running multiple application servers was not supported or needed (citation needed).
This all seems pretty limited, but that’s the point. It gives you just what you need to put a Rails app in production while leaving more advanced scenarios to other tools.
If you need to serve a proof of concept quickly and don’t care about load balancing or zero-downtime updates just yet, Thruster will do the job just fine.
Just set the TLS_DOMAIN
environment variable with your domain (for automatic SSL/TLS) and replace your bin/rails s
command with: bin/thrust bin/rails s
That’s it! Your app is ready for production.
Thruster is mostly zero-config (about 20 environment variables can be used to customize its behavior).
Fast forward a year, and now your service is getting a lot of traffic. This single-server setup is becoming a liability.
No worries! Drop the TLS_DOMAIN
environment variable, place a load balancer in front of multiple Thruster/app instances, and you’re in business!
You might wonder, why use Thruster at all at this point? Wouldn’t the load balancer overlap with Thruster?
Yes, except for sending assets (x-sendfile
and HTTP cache headers). Your load balancer probably doesn’t run with your app on the same machine/container. Thruster does. So it can intercept file requests and free the app server to handle the next request.
Kamal Proxy
Kamal-proxy is a lot closer to general-purpose proxies, but not quite.
Kamal-proxy was unveiled last year by 37signals as a replacement for Traefik (another HTTP proxy) when deploying with Kamal. While Kamal-proxy can be used as a standalone tool, it was specifically designed for Kamal.
The declarative nature of Traefik was causing some trouble. Every Kamal deployment had to wait for Traefik to detect the configuration changes and apply them, which slowed down deployment considerably. It was also difficult to debug state transitions.
To fix these issues, 37signals created Kamal-proxy, a purpose-built imperative proxy.
Kamal-proxy is designed to handle zero-downtime deployments and route requests to different backing services based on the request’s host header. This means it can handle multiple applications living on the same server by routing requests to the correct application.
It does not handle load balancing, but it does support zero-downtime deployments and updates.
Unlike Thruster, Kamal-proxy is configurable via a file, but it is not meant to be manually edited. This configuration acts more like a saved state that persists between server restarts. Configuration changes are made by calling the kamal-proxy command.
In general, you do not interact with Kamal-proxy directly—Kamal manages the proxy for you.
Since Kamal-proxy is designed to sit in front of multiple applications, it has several features that Thruster does not:
- Health checks
- Pausing requests
- Zero-downtime deployments
- Host-based routing
- Path-based routing
What Should I Use?
It depends.
Are you running a single app on a VPS and okay with the app being offline for a minute when you restart it? I still recommend Kamal (easier to deploy), but Thruster alone would work.

Using Kamal to deploy? You want both—Thruster inside the container and Kamal-proxy to route public traffic to the container.

Outside of a Kamal deployment, use Thruster in front of your app, and place your cloud provider’s (or a self-managed) load balancer in front of it.

Summary:
- You almost always want Thruster—it helps serve your files efficiently.
- Then, decide if you need a proxy in front of it.
- Choose the right proxy based on where and how you deploy your app:
- Deploying through Kamal? Use Kamal-proxy.
- Deploying through a container service or PaaS like ECS or Heroku? Use the provided load balancer to route traffic.
- Deploying through a bunch of shell scripts? You probably know what you’re doing.
For more details, watch Kevin McConnell's Rails World 2024 talk: "Introducing Kamal Proxy."