ActiveRecord querying: N+1 detection
This course covers how to detect N+1 queries in a Rails app. It starts with the signature of an N+1 burst in the development log. Then it counts queries from Ruby through the sql.active_record event of ActiveSupport::Notifications. It shows assert_queries_count and related test helpers, including what it takes to call them in an RSpec suite with transactional fixtures. It sets up the Bullet gem, its alert channels, its three detectors and safelisting. Each tool is then placed in development, test or production.
What you'll learn
- ✓Recognizing the N+1 pattern in the Rails log with verbose_query_logs
- ✓Counting queries with an ActiveSupport::Notifications subscription
- ✓Writing assert_queries_count tests and wiring them into RSpec
- ✓Setting up Bullet, its alert channels and Bullet.raise for tests
- ✓Telling Bullet's three detectors apart and safelisting a known false positive
- ✓Choosing detection tools for development, test and production
Recognizing N+1 in the Rails log
ActiveRecord querying: includes & joins spent seven lessons on fixing N+1. .includes, .preload, .eager_load and .strict_loading turn a lazy association access into one extra query, or a loud error, instead of one query per row. All seven lessons assumed you already knew a page had the problem. This…
Read the full lesson free →Curriculum
7 lessonsRecognizing N+1 in the Rails log
Reading the log to spot an N+1 burst: one repeated label, one varying id, a collection-sized count.
Counting queries with ActiveSupport::Notifications
Subscribing to sql.active_record events to count queries from Ruby, skipping cached and SCHEMA entries.
assert_queries_count: catching N+1 in a test
Using assert_queries_count and related helpers, wiring them into RSpec, and accounting for transactional fixture savepoints.
The Bullet gem: setup and alerts
Adding the Bullet gem to the development group, choosing alert channels, and making tests fail with Bullet.raise.
Bullet's three detectors, and when it's wrong
Bullet's three detectors, a false positive from unused eager loading, and silencing it with add_safelist.
Detection at every stage: dev, test, production
Which detection tools cover development, test and production, including strict_loading and APM services such as Scout APM.
Putting it together: from log line to fix
Following one N+1 from log line to fix, comparing two fix shapes, and building a plain Ruby detector.