GraphQL : la lune de miel avec l’entreprise est terminée
(johnjames.blog)- GraphQL cherche à résoudre le problème de sur-sollicitation des données, mais dans la plupart des environnements d’entreprise, ce problème est déjà résolu autrement
- Dans les systèmes d’entreprise où l’architecture BFF (Backend for Frontend) est devenue la norme, l’intérêt principal de GraphQL diminue fortement
- Complexité d’implémentation, baisse de l’observabilité, problèmes de cache, contraintes sur les ID, traitement peu pratique des fichiers : autant de facteurs qui alourdissent le coût en production
- REST est simple et rapide, et facilite la gestion des erreurs comme l’onboarding, ce qui le rend plus efficace dans les environnements avec de grandes équipes
- En conclusion, GraphQL est utile dans certains cas, mais constitue un choix excessif pour la plupart des entreprises
Le problème que GraphQL cherche à résoudre
- L’objectif central de GraphQL est d’éviter l’overfetching (récupération excessive de données inutiles)
- Le client ne demande que les champs nécessaires, ce qui réduit les transferts de données inutiles
- Autre avantage : il n’est pas nécessaire de modifier le backend à chaque nouvelle exigence de l’interface utilisateur
- Mais dans la réalité, cette architecture idéale ne correspond pas à la complexité du terrain
L’overfetching déjà résolu par le BFF
- La plupart des frontends d’entreprise utilisent déjà une couche BFF (Backend for Frontend)
- Elle assemble les données selon les besoins de l’UI, agrège plusieurs appels downstream et masque la complexité du backend
- Un BFF fondé sur REST peut déjà ne renvoyer que les données nécessaires, ce qui duplique l’avantage de GraphQL
- Si la couche GraphQL récupère ses données depuis des API REST, l’overfetching est simplement déplacé d’un niveau plus bas
- GraphQL peut être utile lorsque plusieurs pages partagent le même endpoint, mais
- ce bénéfice revient souvent à accepter davantage de configuration et de maintenance pour économiser quelques kilo-octets
Complexité d’implémentation et baisse de productivité
- GraphQL demande beaucoup plus de temps et de complexité d’implémentation que REST
- Il faut définir le schéma, les types, les resolvers, les sources de données, etc.
- Il faut aussi maintenir la synchronisation entre le schéma et les clients
- GraphQL optimise la consommation (confort côté client), mais au détriment de la production (vitesse de développement côté serveur)
- En environnement d’entreprise, la vitesse de production et la simplicité sont souvent plus importantes
Problèmes d’observabilité et de monitoring
- Le système de codes de statut HTTP de GraphQL est peu cohérent
- Une réponse 200 peut contenir des erreurs, ce qui complique la distinction entre succès et échec dans le monitoring
- Avec REST, les 2XX/4XX/5XX permettent une séparation claire, ce qui rend le filtrage dans les dashboards plus intuitif
- Des outils comme Apollo permettent des personnalisations, mais cela entraîne davantage de configuration et de charge mentale
- En cas d’incident en production, identifier le problème est plus difficile et plus complexe qu’avec REST
Les limites concrètes du cache
- Le cache normalisé (normalized caching) d’Apollo est théoriquement puissant, mais en pratique fragile et complexe
- Deux requêtes qui ne diffèrent que par un seul champ sont traitées séparément, ce qui impose des raccords manuels
- Le débogage du cache devient un problème à part entière
- À l’inverse, REST peut simplement mettre en cache la réponse complète, ce qui le rend plus stable et plus facile à maintenir
Le problème des contraintes sur les champs ID
- Apollo part du principe que tous les objets possèdent un champ id ou _id
- Or, de nombreuses API d’entreprise n’ont pas d’ID unique, ou pas d’identifiant global
- Pour s’adapter à cette contrainte, le BFF doit ajouter une logique de génération d’ID locaux
- Résultat : plus de champs et plus de logique inutiles, ce qui annule en partie le gain sur l’overfetching
L’inefficacité des uploads et téléchargements de fichiers
- GraphQL est mal adapté au traitement des données binaires
- En pratique, on renvoie une URL de téléchargement et le fichier transite via REST
- Inclure de gros volumes de données comme des PDF dans une réponse GraphQL dégrade les performances
- Cela brise l’idéal de l’API unique promis par GraphQL
Onboarding et courbe d’apprentissage
- La plupart des développeurs ont beaucoup d’expérience avec REST, alors que GraphQL demande un apprentissage
- Il faut assimiler de nouveaux concepts : schéma, resolvers, composition des requêtes, règles de cache, gestion des erreurs, etc.
- Cela ralentit l’onboarding des équipes
- REST reste une approche « ennuyeuse mais hautement scalable », donc bien adaptée aux grandes équipes
La complexité de la gestion des erreurs
- Les réponses d’erreur GraphQL sont complexes, avec champs nullable, partial data, tableau
errors, codes de statut étendus, etc.- Il faut en plus retrouver quel resolver a échoué
- Avec REST, un simple 400 ou 500 suffit souvent, ce qui facilite la compréhension et le débogage
Conclusion : GraphQL reste une technologie de niche
- GraphQL est un outil valable dans certaines situations
- Mais dans la plupart des environnements d’entreprise, les problèmes sont déjà résolus avec BFF et REST
- Les vrais enjeux ne sont pas l’overfetching, mais l’observabilité, la fiabilité et la vitesse
- Au final, GraphQL résout un problème étroit au prix d’une complexité plus large
- La conclusion est donc : GraphQL n’est pas mauvais, mais dans la plupart des cas, il n’est pas nécessaire
2 commentaires
Commentaires Hacker News
Je ne suis pas d’accord avec l’idée que le principal problème de GraphQL soit l’overfetching
À mes yeux, ses vrais atouts sont : (a) il impose un contrat strict fondé sur les types, (b) il rend l’évolution du schéma bien plus facile
Grâce au système de types, les entrées et les sorties suivent toujours une forme définie, et l’usage de types scalaires personnalisés (par ex. numéro de téléphone, e-mail, etc.) permet de réduire fortement les bugs et les problèmes de sécurité
En plus, l’ajout de nouveaux champs ou la dépréciation des champs existants sont standardisés, donc la charge cognitive reste faible côté serveur comme côté client
Si j’utilise GraphQL, c’est pour la composition et l’évolution des API. Surtout dans les grands systèmes à structure M:N, le flux « le client décrit ce dont il a besoin → le serveur compose → les services métier résolvent » est bien plus facile à maintenir sur le long terme
Combiné à une bonne observability, cela devient une base très puissante pour l’accès aux données
Un autre avantage est la facilité de réutilisation des resolvers et de federation. En REST, c’est assez pénible
L’évolution du schéma est aussi bien gérée par Protobuf
Le vrai avantage de GraphQL, c’est la possibilité de composer les données d’UI en petits fragments
En utilisant la fragment colocation comme dans cette vidéo, on peut modifier un composant enfant sans impacter le reste
Comme les requêtes sont générées automatiquement à partir des fragments, le risque de casser d’autres composants lors de la suppression d’un champ diminue aussi
Si l’échelle est petite ou que la rapidité de développement n’est pas cruciale, GraphQL peut sembler être un surinvestissement
La colocation est un concept vraiment révolutionnaire, mais Apollo n’en parlait presque pas
La documentation de Relay reste insuffisante, mais le concept d’Entrypoint est excellent
En revanche, l’implémentation de graphql-codegen manque de compatibilité avec les plugins, donc nous avons dû écrire nos propres plugins
Il manque de cohérence dans l’ensemble de l’écosystème
Dire que l’overfetching est le problème central de GraphQL est exagéré
Je vois GraphQL comme un outil qui traite au niveau client le décalage d’impédance que les ORM résolvent
L’utiliser sans tooling basé sur un compilateur comme Relay est un antipattern
Aujourd’hui, comme l’IA génère automatiquement la couche de données, la nécessité de GraphQL semble diminuer
L’expérience développeur (DevEx) est excellente, avec par exemple la génération automatique quand on sélectionne un champ inexistant
La lenteur du web moderne vient en grande partie de la surdiffusion de données. En pratique, beaucoup d’apps fonctionnent avec moins de 0,5 % d’efficacité
J’utilise GraphQL depuis 2016
Fondamentalement, GraphQL est une spécification RPC. On peut l’implémenter comme une map côté serveur de « Action(Args) → ResultType »
Au lieu des multiples endpoints du REST, GraphQL fonctionne via un unique endpoint
/queryet une map de resolversAu final, c’est une structure où les entrées et sorties sont typées, comme avec OpenAPI ou gRPC
Apollo a un peu amélioré les choses en ajoutant le fragment masking, mais une approche centrée sur Relay reste importante
puis que le backend la transforme en une requête SQL unique pour l’exécuter
Les resolvers ne devraient être utilisés qu’exceptionnellement, pour les données qu’on ne peut pas récupérer directement depuis la base
Quand je dirigeais une équipe, le front voulait GraphQL, donc on l’a adopté
Au final, chaque page récupérait toutes ses données via une énorme requête, puis renvoyait à nouveau l’intégralité du blob JSON à chaque modification
L’application fonctionnait, mais comme l’entreprise a finalement pivoté, ce code a disparu
En pratique, beaucoup de projets GraphQL semblent finir comme ça : des implémentations purement formelles
Les flux d’authentification (auth) de GraphQL sont l’un de ses plus gros casse-tête
Comme les resolvers peuvent être appelés dans des contextes variés, il faut prendre en compte tous les cas
La complexité et le coût mental deviennent trop élevés, et au final on finit par verrouiller les champs
J’ai même créé graphql-autharoo moi-même, mais ce n’était pas suffisant
La plupart des fonctionnalités peuvent être implémentées plus simplement sans GraphQL
Il faut ajouter des permissions fines à chaque ressource GraphQL, donc les requêtes ne fonctionnent pas tant que l’ensemble des ressources n’a pas été mis à jour
La charge est telle qu’on en vient à dire : « Autant le refaire en REST »
Je pense qu’il vaut mieux utiliser un framework serveur abouti plutôt que de tout composer soi-même
GraphQL semble séduisant en surface, mais en pratique c’est une technologie de plus en plus difficile à maintenir avec le temps
Comme beaucoup de technologies, cela rappelle au final que une roue reste une roue
L’avantage de GraphQL, c’est qu’il suffit d’ajouter des champs au schéma pour que tous les clients puissent immédiatement les interroger
Les demandes du front du type « il nous faut aussi ce champ » disparaissent, ce qui simplifie la collaboration
Il est aussi facile de créer des snapshots du schéma pour détecter les changements dans les tests d’intégration
J’ai trouvé cela plus cohérent que REST, mais c’est une expérience personnelle
Puisqu’on peut enchaîner les requêtes de A à E, cela aggrave les problèmes de performance ainsi que le couplage entre frontend et structure des données
React aussi part désormais d’un SSR piloté par framework et des server components
Au final, tout évolue vers une intégration client-serveur portée par TypeScript
Je me demande comment GraphQL empêche les problèmes de charge base de données ou de requêtes inefficaces
Une requête malveillante ne pourrait-elle pas faire exploser l’état interne ?
REST est trop ennuyeux, alors j’essaie GraphQL
J’aime l’idée que le serveur et le client puissent se mettre d’accord sur les requêtes et réponses au moment de la compilation
J’aimerais que les blogs ne se contentent pas de dire « ça, c’est nul », mais présentent aussi des technologies alternatives
Les deux technologies résolvent très bien le problème du contrat client-serveur
Il y a sans doute des avantages et des inconvénients, mais concevoir les données et le contrôle d’accès au niveau du schéma, puis devoir ajouter quelque chose dans la REST API à chaque fois qu’on ajoute un élément, pour au final tout renvoyer plus tard, ça me paraît quand même préférable. Les inconvénients sont évidents, mais les avantages le sont tout autant, haha.