How to avoid upstream timeouts?

That is impossible to answer 100% accurately without a proper A-B test, last thing I want to do is bad-mouth Puma, I also have a great relationship with the Puma maintainers.

What our unicorn setup gives us excellent predictability regarding performance. A unicorn worker can only serve one active (non message bus / non hijacked) request at a time. That means quite a few things in the Ruby world.

  1. Due to global interpreter lock, if you start serving more than 1 request per worker you start bottlenecking on the lock making stuff slower.

  2. If you run lots of requests on a single worker concurrently memory usage can spike and you can bloat Ruby heaps

  3. Only clean way of timing out a request is tearing down a process, unicorn makes this very straight forward and the forking model makes the cost of timing out low.

Unicorn has served us enormously well, and I see no plans to experiment with anything else. That said if memory is super tight I can see an advantage to using puma but the behavior of “low memory” + “misbahving app” on a single process puma could be very very painful.