Benito Serna Tips and tools for Ruby on Rails developers

When do you need a counter cache in rails?

Maybe you have heard about the counter cache feature.

It makes finding the number of belonging objects more efficient, by keeping a column with the count.

But… When should you use it? Do you need to have a counter cache for every association count in your app?

Here are three situations when you could need a counter cache.

When you have slow counts in your views

Even if you do the count via SQL, a single count can be slow enough to need a counter cache.

Imagine you need to put the number of likes in a post.

If a post could have thousands or millions of likes, a single count, can really hit the performance of the app.

posts = Post.find(id)

# If there are thousands or millions of likes
# counting via SQL could also be slow
puts "Post likes: #{posts.likes.size}"

In this case you could try a counter cache or maybe fragment caching.

When preloading the counts in a list is slow

Sometimes preloading counts for a list via SQL is not fast enough.

Imagine you need to put the number of likes for each post in a list.

If there could be posts with thousands or millions of likes, the count for a list of posts could be really slow.

Even if you are already just preloading the counts to avoid n+1 queries with something like this:

posts = Post.limit(5)

# If there are thousands or millions of likes per post
# preloading the counts could also be slow
likes = Like.where(post_id: posts).group(:post_id).count

posts.each do |post|
  puts "Post: #{post.id}, likes: #{likes[post.id] || 0}"
end

In this case you could also try a counter cache or maybe fragment caching.

When you use a lot a count in the application

Sometimes you will be using the count in a lot of places in the app.

You will need to preload the count in every place, raising the possibility to introduce n+1 queries.

In this situation it could be a good option to implement a counter cache, even if you already have a preload object.

Related articles

Avoid and fix n+1 queries with total confidence!

You know that includes can sometimes fix the problem… You are just not sure why sometimes it doesn’t?

Learn how you can use active record and other tools to avoid n+1 queries and start shipping performant code.

Get the ebook today