Paginating Ruby on Rails applications with Pagy

As a developer, I've been working with Ruby on Rails applications since version 0.8 and I've lived through the hype and the myriad of RubyGems that appeared in the following years.

As with any software development community that matures, a lot of those libraries didn't have considerable adoption and no one is supporting them today, while others have lived to became the de-facto gem for a specific use.

In some cases we can still opt for one or another gem, but there are champions for most features.

Rails evolution over time

The image below shows how the community contributed with new libraries and ideas in the last 10 years.

New Rubygems per year

We can see the initial growth, the peak in 2015 and the decline (i.e. maturity?) until today. I suspect that 2018 will be very similar to 2009 and, if the trend continues, the number of new gems will also decline in the upcoming years, until it stabilizes.

A lot of questions can be raised around this. Did Rails reach its full potential in 2015? Is the adoption of the platform in decline? Or is this a sign of maturity and Rails is now ready for mass corporate adoption?

I don't think we can objectively reach any conclusion with this data alone. Instead, I would like to follow a different approach and focus on something that could have a great impact on the work we do today.

We can say that, as the numbers decline, it's hard to find something new that will have a good impact on the work we do today. But let me prove you wrong.

Meet Pagy

If you've worked with Ruby on Rails in the past, then you probably used will_paginate or Kaminari to paginate the index pages of your application. If you're new to Rails, you'll be looking for a pagination gem pretty soon.

Pagy is a new pagination library for Ruby on Rails. It was developed with performance in mind, without disregarding being easy to use on a new or existing Ruby on Rails application.

I know what you're thinking:

"Great, another pagination gem is exactly what we need... not!".

I'm with you on this. I don't think fragmentation is a good thing for open source. Plus, some of the improvements that this Gem brings were proposed to be implemented in Kaminari, but were rejected, probably because the improvements would require a lot of changes to the gem's core.

I'm a firm believer that sometimes we need the take a step back and question if what is out there is really the best we can do... and regarding pagination, it's not. Let me show you why.

Pagy, Kaminari and will_paginate memory user per page shown

I believe that the image is self-explanatory.

If your application is serving hundreds or thousands of users simultaneously, it's easy to guess the impact that such a simple feature has on your resources. A test with 20 pages shows a great memory increase in Kaminari, while will_paginate is doing ok. But Pagy can do better, and again, consider the impact this has when you're trying to serve thousands of users.

Let's take a deeper look, this time comparing the memory footprint of each gem:

Pagy, Kaminari and will_paginate total memory used

Pagy is using far less memory than Kaminari for the same job. And yes, will_paginate uses less memory than Kaminari, but it's still 7x more than Pagy. And please take into consideration that the last release of will_paginate was almost a year ago, the git repo has a few dozens of pull requests pending and the last commit dates back to July 2017.

If I had to start a new project, I wouldn't consider this one as an option.

By this time you should be asking:

"Ok, I'm hooked. How is this possible? Why is the memory footprint of Pagy so low when compared to the other options?".

I'm glad you asked. Let me show you this.

Pagy, Kaminari and will_paginate number of objects created

Yep. The first time I saw it I also wondered:

"Why the hell is Kaminari creating more than 6k objects?"

And yes, will_paginate is better, but 3k objects to paginate 20 pages seems excessive, to say the least. Pagy does it with less than 400...

Why is Pagy better?

What's so different in Pagy? Let me tell you.

  • Pagy uses integers for the calculations instead of Ruby objects;
  • The library core code is less than 60 lines of code;
  • It produces its own HTML, URLs, pluralization and interpolation, staying away from your application models;
  • It makes use of specifically-specialized code instead of generic helpers;
  • Because the code is so specific, the author benchmarked it line by line (which is easy to achieve when you're dealing with less than 100 lines of code).

A huge collateral advantage coming from the above facts is that the code is really easy to understand.

It can also be extended via extensions, and there are already a few useful ones built-in - which comes handy.

Further thoughts

I've started developing Rails apps using will_paginate, as it was the best tool for the job at the time. I then jumped to the Kaminari waggon, a few months after it was launched (unfortunately it was so long ago that I don't recall in detail why). I've been using Kaminari until a couple of weeks after Pagy was launched.

What really surprised me when I first became aware of Pagy was that I moved from will_paginate to Kaminari without taking performance into account, while the latter is much slower than the former. And now that I'm aware, I'm concerned.

I wonder how many gems we've been using that really hurts the performance of the apps that we design and deliver.

Moving from will_paginate or Kaminari to Pagy is really easy, and requires just a few lines of code. I promise that my next post will be an how to guide if people show enough interest about this topic.

As a disclaimer, the images and performance used above are from benchmark tests performed by Pagy's author. The source code can be found here. The image regarding RubyGem adoption was built using data from RubyGems and can be found here.

At Imaginary Cloud, we simplify complex systems, delivering interfaces that users love. If you’ve enjoyed this article, you will certainly enjoy our newsletter, which may be subscribed below. Take this chance to also check our latest work and, if there is any project that you think we can help with, feel free to reach us. We look forward to hearing from you!