contactez nous


En bref : selon le benchmark de pagination publié par l'auteur de Pagy, Pagy est de loin la plus légère des trois gems Ruby on Rails les plus populaires. Pour le rendu d'une même navigation sur les mêmes enregistrements, elle alloue 184 objets alors que will_paginate en alloue environ 3 200 et Kaminari environ 6 400. Sur une application servant des milliers d'utilisateurs simultanés, cet écart impacte votre plafond de mémoire par instance, ce qui revient à dire le nombre d'instances que vous payez.
Une précision importante pour commencer, car beaucoup d'articles qui circulent sont datés : Pagy n'est plus le petit nouveau. Lancée en février 2018 , c'est désormais une bibliothèque mature et largement adoptée. Ce qui a changé, c'est l'API. Pagy 43 a été entièrement repensée, si bien que la plupart des tutoriels que vous trouverez (y compris les nôtres jusqu'à présent) présentent des appels qui n'existent plus. Je développe des applications Rails depuis la version 0.8 et j'ai utilisé ces trois gems en production pour la pagination ; cet article a été réécrit pour correspondre à la version actuelle.
Avant de passer aux performances, parlons maintenance, car « lequel est le plus rapide » importe moins que « lequel est toujours suivi » lorsque vous y confiez une base de code pour plusieurs années.
| Gem | Version actuelle | Dernière version | Signal de maintenance |
|---|---|---|---|
| Pagy | 43.x | 2026 | Développement actif ; publications fréquentes ; refonte complète dans la v43 |
| Kaminari | 1.2.2 | Décembre 2021 | Toujours le plus installé de loin, mais aucune version publiée depuis plus d'un an |
| will_paginate | 4.0.1 | Juin 2024 | Officiellement en mode maintenance : aucune nouvelle fonctionnalité, et le README lui-même oriente les utilisateurs vers des alternatives |
Quelques conclusions découlent de ce tableau.
will_paginate n'est pas mort, mais son propre mainteneur a tiré un trait dessus. Il a bénéficié du support de Rails 7 dans la version 4.0 et a reçu un correctif en 2024 ; l'affirmation selon laquelle « le dernier commit remonte à 2017 », que l'on trouve dans d'anciens articles (y compris les nôtres), est donc tout simplement fausse. La bonne raison de l'éviter pour un nouveau projet n'est pas l'abandon. C'est que le mainteneur l'a explicitement placé en mode maintenance et a cessé d'ajouter des fonctionnalités. C'est une base de décision valable, mais un mauvais argument si vous vous appuyez sur une date de commit de 2017.
Kaminari est la référence actuelle, et cela compte toujours. Il possède la plus large base installée des trois, de loin, une documentation approfondie, des modèles de vue que vous pouvez générer et personnaliser, ainsi qu'une configuration par modèle. Mais sa dernière version remonte à décembre 2021. Il fonctionne, il est stable, et sur un panneau d'administration à faible trafic, aucune des questions de performance abordées ci-dessous ne sera perceptible. Cependant, la dynamique est clairement ailleurs.
Pagy est là où se concentre l'énergie du développement actif. Au-delà de sa vitesse brute, il propose désormais plusieurs techniques de pagination dans une seule gem (offset, countless, keyset, keynav, calendrier et recherche), ainsi qu'un rendu côté serveur ou côté client, et des outils de développement interactifs. Cette richesse, et pas seulement les chiffres de consommation mémoire, explique en grande partie pourquoi les gens le choisissent aujourd'hui.
Le nombre de nouveaux RubyGems publiés chaque année a progressé au début des années 2010, a atteint un pic vers 2015, puis a décliné depuis. Cela ne signifie pas qu'aucune nouveauté ne mérite votre attention. Cela signifie que les outils réellement utiles sont devenus plus rares et plus difficiles à repérer. Pagy en faisait partie en 2018 ; l'intérêt d'une mise à jour comme celle-ci est que « rare et facile à manquer » décrit également les évolutions apportées à une bonne bibliothèque une fois que la communauté a cessé d'en parler.
2010 à 2026
Chiffres vérifiés : 2014 (~27 000) et 2018 (~10 600 / ~29 par jour), d'après les analyses RubyGems d'Infinum.
Si vous avez déjà travaillé avec Rails, vous avez probablement utilisé will_paginate ou Kaminari pour paginer les pages d'index d'une application. La pagination consiste à diviser une longue liste d'enregistrements en pages numérotées et à afficher les liens permettant de naviguer entre elles. Si vous débutez avec Rails, vous serez rapidement amené à rechercher une solution de pagination.
Pagy est une bibliothèque de pagination conçue avec la performance comme priorité absolue, tout en restant simple à utiliser sur une application nouvelle ou existante. Elle est indépendante du framework : elle fonctionne avec Rails ainsi qu'avec des frameworks Ruby plus légers comme Sinatra et Padrino, et elle permet de paginer aussi bien des relations Active Record que des tableaux simples ou d'autres collections.
Il était légitime d'être sceptique face à une nouvelle gem de pagination en 2018. La fragmentation n'est pas bénéfique pour l'open source, et certaines des améliorations apportées par Pagy avaient d'abord été proposées pour Kaminari avant d'être rejetées, au motif qu'elles auraient nécessité des changements substantiels au cœur de cette gem. Ce refus est en partie la raison d'être de Pagy. Huit ans plus tard, le scepticisme s'est largement dissipé : le nombre de téléchargements et d'étoiles place désormais Pagy parmi les choix incontournables plutôt que comme une alternative marginale.
Considérez chaque gem sur le chemin d'une requête comme un bagage. Vous le transportez à chaque voyage, que vous l'ouvriez ou non, et la pagination est le sac qui vous accompagne sur presque toutes les pages de listage de votre produit. Un sac lourd n'est pas un problème pour un seul voyage. Cela devient un problème lorsque vous en effectuez dix mille par heure.
Les chiffres qui suivent proviennent de la suite de tests de performance publiée par l'auteur de Pagy, qui génère la même pagination Bootstrap sur les mêmes enregistrements avec chaque gem à tour de rôle.
La suite enregistre deux éléments par gem : la mémoire allouée pour effectuer le travail et le nombre d'objets Ruby alloués. Elle ne mesure pas la requête en base de données derrière la page, qui est identique quel que soit le gem utilisé. Elle ne mesure pas non plus le temps de chargement de la page pour l'utilisateur final, qui est dominé par la requête, la vue et le réseau. De plus, elle est publiée par l'auteur de l'un des trois gems ; considérez-la donc comme une comparaison directe de la surcharge de pagination plutôt que comme un essai indépendant.
Deux précisions honnêtes sur les chiffres ci-dessous. Premièrement, la suite publiée teste toujours les anciennes versions (Pagy v3, will_paginate 3.1.7, Kaminari 1.1.1) ; considérez-les donc comme la surcharge de l'implémentation classique de chaque gem. Deuxièmement, la version actuelle v43 de Pagy revendique des gains supplémentaires par rapport à sa propre base de référence v3 ; si quoi que ce soit, l'écart moderne est donc plus large, et non plus étroit. Les chiffres représentent la surcharge, et rien d'autre.
| Gem (version testée) | Objets alloués | Mémoire totale allouée | Croissance de la mémoire, 2 à 20 pages |
|---|---|---|---|
| Pagy (v3.0.0) | 184 | ~19 Ko | Constante (aucune augmentation mesurable) |
| will_paginate (3.1.7) | ~3 198 | ~341 Ko | ~2x |
| Kaminari (1.1.1) | ~6 445 | ~704 Ko | ~4x |
L'allocation d'objets est là où la différence est la plus frappante. Kaminari crée environ 6 400 objets pour générer la navigation ; will_paginate environ 3 200. Les deux sont trop lourds pour cette tâche. Pagy y parvient avec 184.
La colonne de croissance est tout aussi importante que les totaux. Si vous élargissez la barre de pagination de 2 à 20 liens, l'utilisation de la mémoire par Pagy reste pratiquement stable, celle de will_paginate double environ, et celle de Kaminari quadruple presque. Sur une page de liste très fréquentée avec une barre de pagination étendue, ce coût est répercuté sur chaque requête.
Il y a également une question de taille de code derrière l'aspect mémoire. Pour produire un résultat identique, Pagy représente environ 4 fichiers et ~140 lignes; Kaminari s'étend sur ~36 fichiers, will_paginate sur ~23. Moins de code pour accomplir la même tâche signifie généralement moins d'allocations et moins de complexité à gérer, ce qui se reflète directement ici dans le profil.
Même navigation, mêmes enregistrements. Plus c'est bas, mieux c'est.
Objets Ruby alloués pour générer le même rendu de pagination. Source : Suite de tests de performance de l'auteur de Pagy (ddnexus/pagination-comparison), anciennes versions des gems. Pagy 43 annonce des gains encore supérieurs par rapport à la version v3 servant de référence ici.
Chaque objet alloué est une portion de mémoire occupée, puis récupérée par le ramasse-miettes (le travail de fond effectué par Ruby pour libérer la mémoire inutilisée), et tout cela se produit sur un chemin emprunté par la plupart des pages de liste du produit. Réduire les allocations par requête d'un ordre de grandeur ne rend pas le chargement d'une page sensiblement plus rapide. Cela augmente le nombre de requêtes simultanées qu'une instance donnée peut supporter avant d'avoir besoin d'en ajouter une autre. Sur une facture d'infrastructure basée sur le nombre d'instances, c'est là que se situent les économies, et la migration qui permet d'y parvenir se mesure en heures plutôt qu'en sprints.
Nous observons ce schéma dans nos propres projets. Lorsque nous avons reconstruit FlippedNormals, une place de marché dédiée à l'infographie, l'ancienne plateforme WordPress ne pouvait plus suivre le trafic. Nous l'avons donc migrée vers une application Ruby on Rails personnalisée et transférée sur AWS pour une infrastructure plus évolutive. La migration complète a pris deux mois et a permis d'augmenter le trafic de 4 % après la relance. C'est un cas d'étude utile pour cette discussion précisément en raison de sa structure : un catalogue de plus de 28 000 produits signifie que les pages de liste, de recherche et de navigation sont des points critiques, sollicités à presque chaque requête. Ce sont précisément les pages où le coût par requête d'une gemme de pagination est multiplié par votre trafic, et où le choix effectué au début définit discrètement le plafond de ressources plus tard.
Cela présente un avantage collatéral majeur : le code est réellement facile à lire, ce qui a permis à l'auteur de le profiler ligne par ligne.
La pagination n'est qu'un exemple parmi d'autres d'un modèle plus large, et c'est ce modèle que nous recherchons lors de l'audit d'une stack Rails. Nous appelons cela un audit de ressources des gems. Trois étapes.
1. Inventoriez ce qui s'exécute à chaque requête. Pas l'intégralité du Gemfile, seulement les gems sollicitées sur les pages réellement visitées par votre trafic : les pages d'index et de listage, les résultats de recherche, le tableau de bord. La pagination, la sérialisation, les contrôles d'autorisation et les helpers de vue figurent généralement sur cette liste. Une gem utilisée une fois par jour dans une tâche de fond ne mérite pas d'être mesurée.
2. Mesurez l'allocation, pas le temps écoulé. Le nombre d'objets alloués par requête est l'indicateur qui permet de prédire le comportement d'une application en situation de concurrence, et il est suffisamment stable pour comparer deux implémentations. memory_profiler et benchmark-ips vous fourniront à la fois l'allocation et le temps d'exécution pour une action donnée. La différence entre deux gems pour une même action est généralement évidente dès le premier test.
3. Modélisez le résultat en instances, pas en mégaoctets. Une économie ne devient un argument convaincant que lorsqu'elle est exprimée en capacité supplémentaire : combien de requêtes simultanées une instance peut-elle supporter en plus, et par conséquent, de combien d'instances le même trafic a-t-il besoin. C'est sur ce chiffre qu'un décideur technique peut agir, et c'est lui qui justifie l'effort de migration.
La plupart des applications Rails traînent deux ou trois de ces poids morts. La pagination est celui que nous rencontrons le plus souvent, car elle est choisie très tôt, jamais remise en question, et se situe précisément sur les pages qui reçoivent le plus de trafic.
C'est ici que les anciens guides vous induiront en erreur : les Pagy::Backend / Pagy::Frontend includes, le mot-clé items: et l'assistant pagy_nav sont tous antérieurs à la v43. Voici la configuration actuelle, qui suit le guide de démarrage rapide officiel.
1. Ajoutez la gem, en la verrouillant sur la version mineure (la v43 utilise un numéro de version majeur, donc un verrouillage sur la version mineure vous protège des changements cassants) :
# Gemfile
gem 'pagy', '~> 43.6'Pagy 43 nécessite Ruby 3.3 ou une version ultérieure.
2. Incluez le module de point d'entrée unique dans votre contrôleur d'application :
# app/controllers/application_controller.rb
include Pagy::MethodCet unique include remplace l'ancien système à deux modules (Backend plus Interface) configuration. Les méthodes ne sont chargées automatiquement qu'en cas d'utilisation.
3. Paginez dans l'action du contrôleur. Choisissez un paginateur : :offset correspond au comportement classique, :keyset est le plus rapide pour les grandes collections ordonnées :
# Offset pagination (the familiar page-number behaviour)
@pagy, @records = pagy(:offset, Product.all, limit: 20)
# Keyset pagination (fastest for large, ordered datasets)
@pagy, @records = pagy(:keyset, Product.order(:id).all, limit: 20)Remarque limit :, qui a remplacé l'ancien items : mot-clé.
4. Affichez la navigation dans la vue. Les helpers sont désormais des méthodes de l'objet @pagy :
<%# Server-side navigation bar %>
<%== @pagy.series_nav %>
<%# Or a client-side, responsive variant, styled for Bootstrap or Bulma %>
<%== @pagy.series_nav_js(:bootstrap) %>
<%== @pagy.input_nav_js(:bulma) %>
<%# A "showing 476-500 of 1000" style summary %>
<%== @pagy.info_tag %>C'est tout pour le démarrage rapide. Si vous souhaitez adapter interactivement le thème de votre application ou poser une question à l'IA intégrée de Pagy depuis votre propre application, une seule ligne dans votre head active les outils de développement :
<%== Pagy.dev_tools %>Le changement s'effectue dans le contrôleur et la vue (le fichier qui gère la requête et le modèle qui affiche la page). Le guide de migration officiel le décompose en quelques étapes techniques, et en pratique, la correspondance est quasi directe.
Contrôleur. Les anciens appels se traduisent directement :
# will_paginate
# @records = Product.some_scope.paginate(page: params[:page], per_page: 15)
# Kaminari
# @records = Product.some_scope.page(params[:page]).per(15)
# Pagy
@pagy, @records = pagy(:offset, Product.some_scope, limit: 15)Vue. Remplacez le helper :
<%# will_paginate: <%= will_paginate @records %> %>
<%# Kaminari: <%= paginate @records %> %>
<%== @pagy.series_nav %>Configuration globale. Recherchez le nom de classe de l'ancienne gem dans votre base de code (WillPaginate, Kaminari) et supprimez ses initialiseurs ainsi que tout monkey-patching. Une valeur per_page globale devient Pagy::OPTIONS[:limit] dans un initialiseur Pagy, ou un limit:par appel. Si vous dépendiez de Kaminari .page la portée à l'intérieur des méthodes de modèle, supprimez-la et appliquez plutôt le paginateur dans le contrôleur.
Exécutez ensuite vos tests ou naviguez entre les pages. Tout code hérité restant provoquera une erreur ; supprimez-le donc et réessayez jusqu'à ce que l'application s'affiche correctement. Si vous utilisiez les styles de pagination Bootstrap ou Bulma, le CSS existant fonctionne avec les helpers series_nav de Pagy.
Pagy n'est pas un remplacement immédiat : vous ne pouvez pas simplement échanger la gem et laisser votre code intact. Les noms des helpers diffèrent, chaque vue paginée doit donc être visitée, et la collection n'est plus décorée avec des méthodes de page comme Kaminari le fait pour une relation Active Record. Tout code faisant appel à ces méthodes doit être modifié. Les helpers de Pagy renvoient des chaînes HTML brutes, ce qui est précisément ce qui les rend rapides.
Sur une application avec quelques pages d'index, cela prend un après-midi. Sur une application en comptant cinquante, planifiez cela comme une tâche délimitée et traitez-la comme n'importe quel changement apporté à du code exécuté à chaque requête : avec une revue de code et une vérification des pages. Si vous préférez déléguer cette tâche, c'est le type de travail spécifique que nos services de développement Ruby on Rails prennent en charge.
Une recommandation honnête doit aussi préciser quand ne pas l'utiliser.
Restez sur Kaminari si votre application est déjà profondément structurée autour de cet outil (vous dépendez de ses modèles de vue générés et de sa configuration par modèle), ou si vos pages paginées génèrent un trafic suffisamment faible pour que la différence de consommation mémoire ne se répercute jamais sur votre facture. Kaminari est mature, largement documenté et reste le plus installé des trois. L'argument en faveur de Pagy est un argument de ressources , et il est d'autant plus pertinent que la pagination se situe sur un chemin critique.
will_paginate est plus difficile à recommander pour tout nouveau projet, étant donné que son mainteneur a fermé la porte aux nouvelles fonctionnalités. Mais si vous avez une application stable qui l'utilise déjà et que vous ne subissez aucune pression en termes de performance, « en mode maintenance » ne signifie pas « obsolète ». Il n'y a aucune urgence à migrer pour le simple plaisir de changer.
L'argument des ressources en faveur de Pagy est réel, mais il s'agit d'une option, pas d'une obligation. Adaptez votre choix à votre trafic.
J'ai commencé avec will_paginate, car c'était le meilleur outil à l'époque. Je suis passé à Kaminari quelques mois après son lancement, et j'y suis resté jusqu'à quelques semaines après l'apparition de Pagy.
Ce qui m'a surpris plus tard, c'est que j'étais passé de will_paginate à Kaminari sans prendre en compte la performance, alors que selon les benchmarks publiés, Kaminari est le plus lourd des deux. Aucun test de ma part. Juste par habitude.
Cela soulève une question légitime sur le reste de la stack : combien de gems utilisons-nous qui nuisent silencieusement aux applications que nous concevons et livrons, choisies de la même manière et jamais évaluées depuis ? C'est la question qui sous-tend l'audit ci-dessus, et dans notre travail de livraison, c'est désormais un point systématique plutôt qu'une réflexion après coup, car le coût d'une telle interrogation tardive se traduit par une facture d'infrastructure que personne ne peut justifier. Cette logique s'applique bien au-delà de la pagination, et bien au-delà de Rails. Le framework que vous choisissez fixe un socle. Les bibliothèques que vous y ajoutez fixent le plafond. Le même compromis apparaît lorsque vous choisissez le framework lui-même, comme dans notre comparaison entre Ruby et Python pour le développement web.
Avertissement : les chiffres de performance ci-dessus proviennent de la suite de benchmarks publiée par l'auteur de Pagy (ddnexus/pagination-comparison), exécutée sur les anciennes versions de chaque gem.
Oui, largement. Pagy est passé du statut de nouveau venu à celui de choix incontournable pour la pagination sous Rails, avec des dizaines de millions de téléchargements, des milliers d'étoiles sur GitHub et des mises à jour régulières tout au long de 2026. Le développement actif dans ce domaine se concentre sur Pagy ; Kaminari possède une base installée plus large, mais n'a pas publié de nouvelle version depuis 2021.
Selon les benchmarks de l'auteur, oui, et avec une marge importante en termes de ressources : Pagy alloue environ 184 objets contre environ 6 400 pour Kaminari, et utilise beaucoup moins de mémoire au total. La différence visible pour l'utilisateur lors du chargement d'une page est minime. La différence se manifeste dans le nombre de requêtes simultanées qu'une instance peut traiter.
Ajoutez gem 'pagy', '~> 43.6', ajoutez include Pagy::Method à votre ApplicationController, remplacez chaque appel .paginate(...) / .page(...).per(...) par @pagy, @records = pagy(:offset, scope, limit: N), et remplacez le helper de vue par <%== @pagy.series_nav %>Il ne s'agit pas d'un remplacement direct et chaque vue paginée doit être visitée, mais le changement est circonscrit et facile à annuler.
Oui. Ses calculs s'effectuent sur des entiers plutôt que sur des objets Ruby, son coût n'augmente donc pas avec la taille de la collection. Pour les très grandes tables ordonnées, le paginateur :keyset évite totalement le coûteuxOFFSET en profondeur. La limite que vous finirez par atteindre est celle de la requête de comptage de la base de données, et non celle de la gem de pagination, ce qui est vrai pour les trois.
Pagy est indépendant du framework. Il fonctionne avec Rails ainsi qu'avec des frameworks plus légers comme Sinatra et Padrino, et pagine aussi bien les relations Active Record que les tableaux simples ou d'autres collections. Un ORM (mappeur objet-relationnel) est la couche qui transforme les lignes de base de données en objets ; Active Record est celui intégré à Rails, et Pagy fonctionne en parallèle plutôt que de s'attacher à vos modèles.
Il s'agit d'une refonte complète. La configuration a été réduite à un seul include Pagy::Method, les paramètres ont été considérablement simplifiés et les helpers ont été déplacés vers l'objet @pagy (@pagy.series_nav plutôt que l'ancienne méthode pagy_nav(@pagy)). Il a également ajouté de nouveaux paginateurs (countish, keyset, keynav, calendar et search), le rendu côté client et des outils de développement interactifs. Si vous suivez un tutoriel plus ancien, attendez-vous à ce que les noms des méthodes diffèrent.
Chez Imaginary Cloud, nous maîtrisons une vaste pile technologique, incluant Ruby on Rails. Si la pagination ralentit votre application ou si vous soupçonnez que certaines gems consomment plus de ressources que nécessaire, nous pouvons réaliser l'audit de ressources décrit ci-dessus sur votre stack afin d'identifier précisément l'origine de ces coûts. Contactez-nous et nous étudierons cela ensemble.


CEO @ Imaginary Cloud et co-auteur du livre Product Design Process. J'aime la nourriture, le vin et le Krav Maga (pas nécessairement dans cet ordre).
People who read this post, also found these interesting: