Rails.application.config.middleware.insert_before(
Rack::Runtime,
Rack::Timeout,
service_timeout: 15 # 15 seconds
)
# Log timeout errors
Rack::Timeout.register_state_change_observer(:logger) do |env, info|
if info[:state] == :timed_out
Rails.logger.error("Request timeout: #{env['REQUEST_METHOD']} #{env['PATH_INFO']} exceeded 15s")
end
end
class ApplicationController < ActionController::Base
rescue_from Rack::Timeout::RequestTimeoutException, with: :handle_timeout
private
def handle_timeout
render json: {
error: 'REQUEST_TIMEOUT',
message: 'The request took too long to process'
}, status: :service_unavailable
end
end
Long-running requests tie up worker threads and degrade overall application responsiveness. Rack::Timeout enforces request timeouts at the Rack layer, killing requests that exceed configured limits. I set conservative timeouts (15-30 seconds) and handle Rack::Timeout::RequestTimeoutException to return proper 503 Service Unavailable responses. Timeouts protect against slow database queries, hung external API calls, or resource exhaustion. The challenge is distinguishing between legitimately slow operations and bugs—I use monitoring to track timeout rates and investigate patterns. For known slow operations like report generation, I move them to background jobs rather than fighting with timeout configuration.
Related snips
class CommentsController < ApplicationController
before_action :set_post
def create
@comment = @post.comments.build(comment_params)
System test: asserting Turbo Stream responses
class Post < ApplicationRecord
belongs_to :author, class_name: 'User'
has_many :comments, dependent: :destroy
scope :published, -> { where.not(published_at: nil).where('published_at <= ?', Time.current) }
scope :draft, -> { where(published_at: nil) }
ActiveRecord scopes for reusable query logic
export interface RetryOptions {
retries: number;
baseMs: number;
maxMs: number;
signal?: AbortSignal;
onRetry?: (attempt: number, delay: number, err: unknown) => void;
Exponential backoff with jitter for retries
module Api
module V1
class UsersController < BaseController
def show
user = User.includes(:profile).find(params[:id])
ETags for conditional requests and caching
class PostsController < ApplicationController
def index
@posts = Post.includes(:author)
.order(created_at: :desc)
.page(params[:page])
.per(10)
Turbo Frames: infinite scroll with lazy-loading frame
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
Share this code
Here's the card — post it anywhere.