Rails.application.configure do
# Bullet configuration
config.after_initialize do
Bullet.enable = true
Bullet.alert = true # Show JavaScript alert
Bullet.bullet_logger = true # Log to bullet.log
Bullet.console = true # Show in browser console
Bullet.rails_logger = true # Add to Rails log
Bullet.add_footer = true # Add warning to HTML footer
# Raise errors in tests
Bullet.raise = true if Rails.env.test?
end
end
# BAD - N+1 query (1 query for posts + N queries for authors)
def index
@posts = Post.published.limit(20)
render json: @posts.map do |post|
{
title: post.title,
author_name: post.author.name # N queries!
}
end
end
# GOOD - Eager loading (2 queries total)
def index
@posts = Post.published
.includes(:author)
.limit(20)
render json: @posts.map do |post|
{
title: post.title,
author_name: post.author.name # No additional queries
}
end
end
N+1 queries are the most common Rails performance problem—loading associations in loops causes exponential database queries. The Bullet gem detects N+1s in development and suggests fixes. It monitors queries and alerts when you should use includes, preload, or eager_load. I configure it to show notifications in the browser console and raise errors in tests. The gem also catches unused eager loading, where you preload associations but never access them. Fixing N+1s typically involves adding includes(:association) to queries. For complex nested associations, I use strict_loading mode to catch issues early. Bullet is essential tooling—it finds issues CI can't catch.