API Design : REST vs GraphQL et au-delà
REST, GraphQL, gRPC : ce que chaque style d'API impose au client et au serveur, et comment choisir selon votre usage plutôt que selon la mode.
INSIGHTS ADSERVIO · DEVSECOPS

EN BREF
- REST n'est pas défini par JSON, les URLs en /api/v1/ ou le CRUD, mais par une architecture orientée ressources, stateless, avec des verbes HTTP et des codes de statut utilisés correctement.
- GraphQL résout l'over-fetching et l'under-fetching de REST grâce à des requêtes qui décrivent exactement les champs voulus, au prix d'une complexité de cache et d'outillage plus élevée.
- Le choix dépend du contexte : REST pour du CRUD simple avec un fort besoin de caching HTTP, GraphQL pour des clients multiples avec des besoins de données hétérogènes.
- Une approche hybride combinant REST pour les opérations simples et GraphQL pour les vues composites est souvent la meilleure réponse.
- Les bonnes pratiques transverses, naming cohérent, pagination adaptée au volume et rate limiting explicite, comptent autant que le choix REST ou GraphQL.
SECTION 1
Introduction
Votre API est votre contrat avec le monde. Elle définit comment vos clients interagissent avec votre système. REST a dominé pendant 20 ans, GraphQL promet de résoudre ses limitations, mais quelle est la bonne approche pour votre cas d'usage ?
Spoiler : Ce n'est pas "soit l'un, soit l'autre".
SECTION 2
REST : Les fondamentaux (souvent mal compris)
Ce que REST signifie vraiment. REST n'est pas seulement utiliser du JSON sur HTTP, préfixer ses URLs en /api/v1/, ou faire du CRUD basique : ce sont des habitudes répandues, pas la définition du style architectural.
REST est avant tout une architecture basée sur les ressources, avec une communication stateless, une utilisation correcte des verbes HTTP et, dans sa forme la plus aboutie, du HATEOAS (Hypermedia as the Engine of Application State). Concrètement, cela signifie exposer des ressources identifiées par une URL, GET /api/v1/users/123, DELETE /api/v1/users/123,plutôt que des actions déguisées en endpoints comme POST /api/getUserById ou GET /api/users?action=delete&id=123, imbriquer les ressources liées (GET /api/v1/users/123/orders) et exposer le filtrage, le tri et la pagination via des paramètres de requête (GET /api/v1/orders?status=pending&sort=-created_at&page=2&limit=20).
### Versioning
La question du versioning se pose vite. Trois approches coexistent : le versioning dans l'URL (/api/v1/... puis /api/v2/...), le plus explicite et le plus utilisé en pratique ; le versioning par header (Accept-Version : v2) ; et la négociation de contenu via un header Accept personnalisé (application/vnd.company.v2+json). La première option reste la plus simple à documenter et à faire vivre dans le temps.
### Codes de statut HTTP
Le choix du code de statut HTTP fait aussi partie du contrat. Côté succès : 200 pour une lecture ou une mise à jour réussie, 201 pour une création (avec un header Location vers la ressource créée), 204 pour une suppression sans contenu à retourner. Côté erreurs client : 400 pour une erreur de validation, 401 quand l'authentification est requise, 403 quand elle est présente mais insuffisante, 404 pour une ressource inexistante, 409 pour un conflit (doublon, mise à jour concurrente) et 422 pour une erreur sémantique. Côté serveur, 500 signale une erreur interne et 503 une indisponibilité temporaire (maintenance, surcharge).
SECTION 3
GraphQL : Quand et pourquoi
Le problème que GraphQL résout : l'over-fetching. En REST, un endpoint GET /api/users/123 renvoie souvent l'intégralité de la ressource, nom, email, téléphone, adresse, bio, préférences, réglages, et une cinquantaine de champs au total, même quand le client n'a besoin que du nom et de l'email. Avec GraphQL, le client formule une requête qui décrit exactement les champs voulus (query { user(id : "123") { name email } }) et ne reçoit que cela.
L'autre problème est l'under-fetching : reconstituer un écran nécessite souvent plusieurs appels REST successifs, par exemple récupérer l'utilisateur, puis ses posts, puis ses followers. GraphQL permet de regrouper ce besoin en une seule requête imbriquée qui récupère l'utilisateur, ses posts et leurs commentaires, ainsi que ses followers, en un seul aller-retour réseau.
### Schéma, résolveurs et problème N+1
Techniquement, une API GraphQL s'appuie sur un schéma qui type les entités (User, Post, Comment) et les opérations disponibles, Query pour la lecture, Mutation pour l'écriture, Subscription pour le temps réel. Chaque champ du schéma est ensuite relié à un résolveur, une fonction qui va chercher la donnée correspondante en base ou via un service.
Un piège classique des résolveurs imbriqués est le problème N+1 : résoudre les posts de N utilisateurs déclenche une requête par utilisateur en plus de la requête initiale. Le pattern DataLoader (éviter N+1) résout ce problème en regroupant (batching) les identifiants demandés dans le même cycle d'exécution pour ne faire qu'une seule requête groupée du type WHERE author_id IN (...), ramenant le nombre de requêtes de N+1 à 2.
SECTION 4
Quand utiliser quoi
Utilisez REST si : API publique simple (CRUD) ; Besoin de caching HTTP fort ; Équipe pas familière avec GraphQL ; File uploads fréquents ; Relations simples entre entités
Utilisez GraphQL si : Clients multiples avec besoins différents (web, mobile, IoT) ; Graphe complexe de données ; Besoin de real-time (subscriptions) ; Équipe expérimentée ; Contrôle fin sur les données récupérées
Approche hybride : rien n'empêche de combiner les deux. REST reste pertinent pour du CRUD simple et prévisible (POST/GET/PUT/DELETE sur /api/v1/users), tandis que GraphQL prend le relais sur les vues composites, comme un tableau de bord qui agrège en une seule requête le profil utilisateur, ses commandes récentes, ses notifications et ses recommandations.
@cite:monter-une-equipe-api-platform
SECTION 5
API Design Best Practices
### Naming conventions cohérentes
Les noms de ressources doivent rester au pluriel et cohérents d'une route à l'autre (/api/v1/users, /api/v1/orders, /api/v1/products), sans mélanger singulier et pluriel (/api/v1/order) ni glisser de verbe dans l'URL (/api/v1/getAllProducts), l'action est portée par le verbe HTTP, pas par le chemin.
### Pagination
Deux approches dominent : la pagination par curseur (GET /api/v1/posts?cursor=...&limit=20, avec un indicateur hasNextPage et un nextCursor en réponse), recommandée pour les grands volumes de données car elle reste stable même quand la donnée change entre deux appels ; et la pagination par offset (GET /api/v1/posts?page=2&limit=20), plus simple à implémenter et à consommer mais moins fiable sur de gros datasets en évolution constante.
### Rate limiting
Exposer les quotas dans les headers de réponse (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) permet aux clients d'anticiper la limite. Quand elle est dépassée, l'API doit répondre 429 Too Many Requests avec un header Retry-After et un corps expliquant la limite, la fenêtre de temps et le délai avant nouvelle tentative.
@cite:securiser-ses-apis
SECTION 6
REST vs GraphQL : comparaison
En synthèse, REST et GraphQL se distinguent sur plusieurs critères. La courbe d'apprentissage est faible pour REST, moyenne à élevée pour GraphQL. REST souffre nativement d'over-fetching et d'under-fetching, un problème que GraphQL résout par construction. Le versioning est explicite en REST (v1, v2) alors que GraphQL préfère la dépréciation progressive de champs.
Le caching HTTP natif (CDN) fonctionne nativement avec REST, quand GraphQL demande une stratégie de cache plus élaborée. L'upload de fichiers reste plus simple en REST (multipart) qu'en GraphQL. Le temps réel nécessite un WebSocket séparé en REST, alors que les subscriptions sont natives en GraphQL.
La gestion d'erreurs s'appuie sur les codes de statut HTTP en REST, contre une réponse toujours en 200 accompagnée d'un tableau d'erreurs en GraphQL. Côté outillage, REST s'appuie sur Swagger/OpenAPI et GraphQL sur son propre Playground. Enfin, la performance de REST est prévisible, celle de GraphQL dépend fortement des requêtes envoyées par le client.
SECTION 7
Conclusion
Il n'y a pas de gagnant absolu entre REST et GraphQL.
Choisissez en fonction de : - Complexité de vos données - Diversité de vos clients - Compétences de l'équipe - Besoins en caching - Contraintes de performance
Et n'oubliez pas : vous pouvez avoir les deux !
FAQ
Questions fréquentes
REST signifie-t-il simplement utiliser du JSON sur HTTP ?
Non. REST est un style architectural basé sur les ressources, une communication stateless, une utilisation correcte des verbes HTTP et des codes de statut, et idéalement HATEOAS. Utiliser JSON, préfixer ses URLs en /api/v1/ ou faire du CRUD sont des pratiques courantes, mais ne définissent pas REST à elles seules.
Quel est l'intérêt principal de GraphQL par rapport à REST ?
GraphQL résout l'over-fetching (recevoir trop de champs non utilisés) et l'under-fetching (devoir enchaîner plusieurs appels pour reconstituer une vue), en laissant le client décrire exactement les données dont il a besoin dans une requête unique.
Faut-il choisir entre REST et GraphQL ou peut-on les combiner ?
Les deux peuvent coexister. REST reste adapté au CRUD simple avec un fort besoin de caching HTTP, tandis que GraphQL est pertinent pour des clients multiples aux besoins hétérogènes ou des vues composites complexes. Une approche hybride, REST pour les opérations simples et GraphQL pour l'agrégation, est fréquente en production.
À PROPOS D'ADSERVIO
Adservio est un partenaire de transformation digitale AI-native : DSI augmentée par l'IA, ingénierie logicielle, DevOps, MLOps, cybersécurité et gouvernance IA.
Discutons de votre projet : hello@adservio.fr · adservio.fr/contact