EN
en direct

GitHub réduit l’API star history de 2 511 à 24 requêtes en filtrant avant d’agréger

Le 14 octobre 2026, GitHub détaille la réécriture de son endpoint stargazers, qui exigeait 2 511 requêtes pour reconstruire la courbe de react/react et se faisait moissonner pour du spam. La leçon est transposable à toute API : réduire la réponse ne réduit pas le coût de la requête, c’est l’ordre du travail en base qu’il faut changer.

Un compteur mécanique à impulsion posé sur une pile de dossiers papier non triés, aucune page tournée.

14 octobre 2026. GitHub publie un technical deep dive sur la réécriture de son endpoint GET /repos/{owner}/{repo}/stargazers. 2 511 requêtes. C’est ce qu’il fallait autrefois pour reconstruire la courbe de croissance de react/react et ses 251 000 étoiles. 24 requêtes. C’est ce qu’il en coûte aujourd’hui. Pourquoi c’est important : l’histoire vaut pour toutes les équipes qui exposent une API — l’ancien design renvoyait des identités là où les utilisateurs voulaient des tendances, et il faisait travailler la base de données pour rien à chaque appel.

Des identités là où il fallait des courbes

L’endpoint d’origine répondait à une question simple : qui a mis une étoile à ce dépôt ? Il renvoyait une liste paginée de personnes — au maximum 100 par page — et, avec un media type personnalisé, la date à laquelle chaque étoile avait été posée. Le modèle de données était bâti pour ce même usage : il enregistre l’ensemble courant des personnes qui ont mis une étoile, ce qui rend simple l’affichage d’un compteur ou d’une liste. Il n’a jamais été conçu comme un journal d’événements historiques.

Quand les outils ont commencé à lire cette liste comme une série temporelle, reconstruire une courbe de croissance signifiait rapatrier des identités individuelles et traiter chaque étoile courante. Le travail grandissait avec la popularité du dépôt : pour react/react, environ 2 511 requêtes, si bien que les outils butaient sur les limites de débit ou échantillonnaient des pages au lieu de tout lire.

Deux problèmes en découlaient, aux deux extrémités. Les identités étaient disponibles en masse, et des acteurs malveillants ont commencé à moissonner les listes de stargazers publiques pour des campagnes de spam et de phishing. Et pour les dépôts très étoilés, l’endpoint pouvait faire traiter à la base des milliers d’entrées pour renvoyer une seule page.

Le vrai coût était en base, pas dans la réponse

La correction semblait évidente : renvoyer des compteurs au lieu de personnes. Mais renvoyer moins de données ne rendait pas la requête moins chère. À cause d’un bug dans l’implémentation de la pagination, chaque requête comptait toutes les étoiles du dépôt pour calculer le nombre de pages, alors même que l’appelant ne recevait qu’une page de 100 personnes au plus. Sur un dépôt très étoilé, cela signifiait compter des milliers d’entrées à chaque appel.

Les chiffres sont éloquents. Dans la semaine qui a précédé la restriction d’accès, près de 37 000 de ces requêtes de comptage ont été assez lentes pour être journalisées, avec une moyenne de 3 secondes chacune, et les garde-fous de la base en ont tué plus de 1 000 — contribuant directement aux délais d’attente dépassés. Après la restriction, la base a servi environ 60 % de requêtes stargazers en moins, et le temps total passé sur la requête de comptage a chuté d’environ 80 %.

GitHub a donc d’abord restreint l’accès aux listes de stargazers et de watchers aux administrateurs et collaborateurs du dépôt. Côté sécurité, cela a fermé la voie de moissonnage. Côté outils, cela a cassé ceux qui reconstruisaient la courbe à partir de l’ancienne réponse.

Les approches écartées

La première idée a été de conserver un enregistrement par étoile en retirant l’identité : renvoyer starred_at sans le stargazer pour les appelants sans accès collaborateur. C’était le chemin le plus rapide, et il fermait le moissonnage avec un changement léger de la sérialisation. Mais les consommateurs auraient encore dû paginer des milliers d’enregistrements pour construire un historique agrégé — et le nouveau besoin restait attaché à un endpoint et à un modèle de pagination pensés pour lister des personnes, pas pour lire des tendances.

L’agrégation semblait l’étape suivante évidente. Au lieu d’une ligne par étoile, la requête regrouperait les étoiles en buckets quotidiens ou hebdomadaires, puis paginerait un résultat bien plus petit. Le problème était l’endroit où la pagination s’applique. Dans une requête SQL naïve, la base trouve d’abord toutes les étoiles, les regroupe en buckets, les trie — puis seulement applique LIMIT et OFFSET. Pour un dépôt populaire, une requête anonyme aurait encore scanné et agrégé des milliers d’entrées d’index pour renvoyer une poignée de buckets. Pour react/react, lire tout l’historique ainsi aurait signifié examiner environ 6 millions de lignes, car chacune des 24 requêtes aurait retraité toutes les étoiles. Réduire la réponse ne réduisait pas le coût : il fallait réduire le travail avant l’agrégation.

Filtrer avant de grouper

Le design livré pagine l’historique des étoiles par semaine calendaire. Chaque requête traduit page et per_page en une plage de created_at indexée, filtre les étoiles sur ces semaines, puis groupe les enregistrements restants en comptes quotidiens. Une réponse couvre jusqu’à 30 semaines, et augmenter la page remonte dans l’historique du dépôt.

L’ordre des opérations change tout. Avec la plage de dates appliquée en premier, chaque requête ne traite que les semaines renvoyées, et non plus toutes les étoiles courantes. Pour les outils, une seule requête couvre désormais jusqu’à 30 semaines d’historique, quel que soit le nombre d’étoiles. Pour react/react, cela donne environ 24 requêtes au lieu de 2 511, et la base examine chaque étoile à peu près une fois — environ 251 000 lignes sur tout l’historique. Le format de réponse reprend la même forme que l’endpoint d’activité de commits hebdomadaire, GET /repos/{owner}/{repo}/stats/commit_activity, ce qui aligne l’API sur une convention déjà connue.

Deux limites assumées subsistent. La plage de temps borne chaque requête à une période définie, mais pas le nombre d’étoiles dans cette plage : une semaine anormalement dense peut encore produire une requête lente. Et le travail de comparaison a révélé d’autres endroits où GitHub comptait les étoiles à la demande — la page stargazers de github.com, qui passait par le même comptage, utilise désormais le compteur d’étoiles en cache, et ses requêtes lentes hebdomadaires sont tombées à zéro.

La réécriture ne s’est pas faite en vase clos. Quand la restriction d’accès a cassé l’outil populaire Star History, ses utilisateurs se sont mobilisés autour du projet, et l’équipe communauté de GitHub a mis les mainteneurs en relation avec l’ingénierie produit, qui a travaillé à leurs côtés pour concevoir l’endpoint dédié. Un breaking change s’est transformé en collaboration qui a produit un meilleur défaut pour tout le monde.

Verdict

C’est une leçon d’architecture d’API qui se transpose à n’importe quel service exposé. Si vous renvoyez une liste que vos consommateurs réduisent eux-mêmes en agrégat, regardez d’abord ce que fait votre base de données derrière : un LIMIT ne réduit pas le regroupement et le tri déjà exécutés, il ne fait que rogner la réponse. Si vos données incluent des identités qui ne servent à rien côté client, retirez-les — tout ce qui dépasse le besoin est une donnée que quelqu’un d’autre peut détourner. Si vous devez paginer un historique, filtrez sur une plage indexée avant de grouper, et alignez la forme de réponse sur une convention existante. La courbe d’étoiles de react/react ne se reconstruit plus en 2 511 requêtes : elle tient en 24, et c’est l’ordre du travail en base qui a fait la différence, pas la taille de la réponse.

Références

Le brief cyber, chaque mardi

Les failles qui comptent, les correctifs à appliquer, en dix minutes de lecture.

Pas de spam. Désinscription en un clic.
à lire ensuite

Sur le même sujet

Railway suspend ses déploiements après l’accès non autorisé aux variables d’environnement de ses clients

Le 22 octobre 2026, la plateforme d’hébergement Railway avertit ses utilisateurs qu’un tiers non autorisé a pu obtenir le contenu déchiffré de variables d’environnement stockées sur sa plateforme, soit des clés API et des identifiants de registre. Faites tourner tous vos secrets immédiatement, en commençant par les clés des fournisseurs d’inférence d’IA.

← Retour au fil

Tapez au moins deux caractères.

↑ ↓ naviguer ↵ ouvrir esc fermer