All posts

Fix Load Balancer Error in Ruby

Resolve load balancer issues for Ruby web apps using Sinatra, Rack, or Puma, covering proxy headers and connection keep-alive settings.

Ruby Web Apps Behind Load Balancers

Whether you're using Sinatra, Hanami, or raw Rack, Ruby web apps behind a load balancer need proxy header handling and proper server configuration.

Rack Proxy Headers

Use the rack-proxy-headers middleware or handle it manually:

# config.ru
require 'rack'

class ProxyFix
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['HTTP_X_FORWARDED_PROTO'] == 'https'
      env['rack.url_scheme'] = 'https'
      env['HTTPS'] = 'on'
    end
    if env['HTTP_X_FORWARDED_FOR']
      env['REMOTE_ADDR'] = env['HTTP_X_FORWARDED_FOR'].split(',').first.strip
    end
    @app.call(env)
  end
end

use ProxyFix
run MyApp

Puma Configuration

# config/puma.rb
bind 'tcp://0.0.0.0:3000'
workers ENV.fetch('WEB_CONCURRENCY', 2).to_i
threads_count = ENV.fetch('RAILS_MAX_THREADS', 5).to_i
threads threads_count, threads_count

# Important for load balancers
first_data_timeout 30
persistent_timeout 20

The persistent_timeout should be shorter than your load balancer's idle timeout to prevent connection reuse errors.

Sinatra Health Check

get '/healthz' do
  status 200
  'ok'
end

Keep-Alive Mismatches

If you see intermittent 502 errors, it's usually because Puma closes keep-alive connections before the load balancer expects. Align the timeouts:

ALB idle timeout: 60s
Puma persistent_timeout: 75s  ← Keep higher than ALB

Bugsly's Ruby integration captures exceptions from any Rack-based framework, including the real client IP after proxy header processing.

Try Bugsly Free

AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.

Get Started Free