# Speed Up Your Rails App by Squashing N+1 Queries

DevFeed: [Speed Up Your Rails App by Squashing N+1 Queries](<https://devfeed.tech/articles/speed-up-your-rails-app-by-squashing-n-1-queries-20119.md>)

Original publisher: [Read original article](<https://hashrocket.com/blog/posts/speed-up-your-rails-app-by-squashing-n-1-queries>)

Author: Tony Yunker

Published: 2025-11-20T14:00:00Z

Content type: tutorial

Language: en

Sources: [Hashrocket](<https://devfeed.tech/sources/hashrocket.md>)

Topics: [Rails](<https://devfeed.tech/topics/rails.md>), [Databases](<https://devfeed.tech/topics/databases.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [activerecord](<https://devfeed.tech/tags/activerecord.md>), [code](<https://devfeed.tech/tags/code.md>), [database](<https://devfeed.tech/tags/database.md>), [performance](<https://devfeed.tech/tags/performance.md>), [rails](<https://devfeed.tech/tags/rails.md>), [ruby-on-rails](<https://devfeed.tech/tags/ruby-on-rails.md>)

## AI overview

This tutorial explains how N+1 queries arise in Rails applications when associated ActiveRecord records are accessed during iteration. It uses nested authors, posts, and tags as a case study, showing how eager loading can reduce a workload from 1,101 database queries to 3.

## Source excerpt

N+1 queries are one of the most common performance killers in Rails apps, but also one of the easiest to fix. In this post, we'll see how a single line of code can reduce 1,101 database queries down to 3. N+1s occur in rails when you have associated ActiveRecord models, and iterate over one model while accessing fields on the associated records. This might be easier to explain with an example. Let's say you have the following ActiveRecord models: class Author < ApplicationRecord has_many :posts end class Post < ApplicationRecord belongs_to :author has_many :tags end class Tag < ApplicationRecord belongs_to :post end An author has many posts, and each post can have many tags. If we want to list each author and their blog posts like below, then we'll make 1 query to the database for the authors, and then another query for each author's blog posts. For N authors, that's 1 + N queries to the database. Author.take(3).each do |author| puts author.name author.posts.each do |post| puts post.title end end We can see all the queries in the logs - 1 query for authors, then 3 queries for each author's blog posts: Author Load (31.4ms) SELECT "authors".* FROM "authors" Post Load (2.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."author_id" = 163 Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."author_id" = 164 Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."author_id" = 165 In small doses this isn't a big deal - these are small, quick queries. However, as soon as the data gets larger, the queries more complex, or the cardinality of these queries grow, then things can really slow down. Let's look at a case study, where we start with an unoptimized query with 2 layers of N+1s, and see how much faster we can make it. Case 1 - The Unoptimized Query Let's take the example above, and add another layer to it. On our authors index page, we want to list each author, then each of their blog posts, including their associated tags. With a totally unoptimized qu