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

Do you feel bad for asking for help to fix an n+1 queries problem?

Making things work isn't enough for you any more? Now you need to consider performance and scalability?

... But you normally have troubles fixing n+1 queries and trying to find why active record is ignoring your "includes"?

Are you are worried because you feel unqualified to tackle tasks with complex data models?

Sign up to learn how to fix n+1 queries on Rails