API REST vs GraphQL : Quel choix pour votre projet en 2025 ?

Comparatif complet entre API REST et GraphQL en 2025 : principes, avantages, inconvénients, performances, cas d'usage et exemples de code concrets pour Node.js/Express et Apollo Server.

Introduction : REST ou GraphQL, le grand débat de 2025

En 2025, le choix entre REST (Representational State Transfer) et GraphQL reste l'une des décisions architecturales les plus importantes lors de la conception d'une API. REST, créé en 2000, est le standard historique utilisé par des millions d'applications. GraphQL, introduit par Facebook en 2015, promet une alternative plus flexible et efficace.

Mais lequel choisir pour votre projet ? Ce guide complet vous aide à comprendre les forces et faiblesses de chaque approche, avec des exemples concrets et des recommandations basées sur vos besoins réels.


Qu'est-ce qu'une API REST ?

REST (Representational State Transfer) est un style d'architecture basé sur le protocole HTTP. Une API REST expose des ressources (users, posts, products...) accessibles via des endpoints utilisant les méthodes HTTP standard.

Principes fondamentaux de REST

  • Ressources identifiées par URL : /users/123, /posts/456
  • Méthodes HTTP : GET (lecture), POST (création), PUT/PATCH (modification), DELETE (suppression)
  • Stateless : chaque requête contient toutes les informations nécessaires
  • Cacheable : les réponses peuvent être mises en cache (HTTP headers)
  • Uniform Interface : interface standardisée et prévisible

Exemple d'API REST

// Récupérer un utilisateur
GET /api/users/123

// Créer un article
POST /api/posts
Body: { "title": "Mon article", "content": "..." }

// Mettre à jour un utilisateur
PATCH /api/users/123
Body: { "email": "newemail@example.com" }

// Supprimer un article
DELETE /api/posts/456

Qu'est-ce que GraphQL ?

GraphQL est un langage de requête pour API développé par Facebook en 2012 et open-sourcé en 2015. Contrairement à REST, GraphQL expose un point d'entrée unique et permet au client de spécifier exactement les données dont il a besoin.

Principes fondamentaux de GraphQL

  • Un seul endpoint : généralement /graphql
  • Schema fortement typé : définit types, queries, mutations
  • Client demande ce qu'il veut : pas d'overfetching ni underfetching
  • Introspection : le schema est auto-documenté
  • Résolution de requêtes complexes : relations imbriquées en une seule requête

Exemple de requête GraphQL

// Récupérer un utilisateur avec ses posts et commentaires
query {
  user(id: "123") {
    name
    email
    posts {
      title
      comments {
        content
        author {
          name
        }
      }
    }
  }
}

Cette requête renvoie exactement les champs demandés, avec toutes les relations, en une seule requête HTTP.


Comparaison approfondie : REST vs GraphQL


1. Structure et endpoints

AspectRESTGraphQL
EndpointsMultiple (un par ressource)Un seul (/graphql)
StructureBasé sur ressourcesBasé sur schema
DocumentationSwagger/OpenAPI (externe)Introspection native

Exemple REST :

GET /api/users          // Liste des utilisateurs
GET /api/users/123      // Un utilisateur
GET /api/users/123/posts // Posts d'un utilisateur
GET /api/posts/456/comments // Commentaires d'un post

Exemple GraphQL :

POST /graphql
Body: { "query": "{ users { id name } }" }

2. Overfetching et Underfetching

Problème d'Overfetching (REST)

Avec REST, l'endpoint renvoie souvent plus de données que nécessaire.

// Je veux juste le nom et l'email
GET /api/users/123

// Mais je reçois TOUT :
{
  "id": 123,
  "name": "John",
  "email": "john@example.com",
  "phone": "+33...",
  "address": { ... },
  "preferences": { ... },
  "createdAt": "...",
  "updatedAt": "..."
}

➡️ Gaspillage de bande passante (surtout mobile)

Problème d'Underfetching (REST)

Parfois, il faut plusieurs requêtes pour obtenir toutes les données nécessaires.

// 1. Récupérer l'utilisateur
GET /api/users/123

// 2. Récupérer ses posts
GET /api/users/123/posts

// 3. Pour chaque post, récupérer les commentaires
GET /api/posts/1/comments
GET /api/posts/2/comments
GET /api/posts/3/comments

// = 5+ requêtes HTTP

➡️ Problème N+1 : latence élevée

Solution GraphQL

// Une seule requête pour tout
query {
  user(id: "123") {
    name
    email
    posts {
      title
      comments {
        content
      }
    }
  }
}

// ✅ Exactement les champs demandés
// ✅ Une seule requête HTTP

3. Versioning

AspectRESTGraphQL
VersioningNécessaire (/api/v1/, /api/v2/)Pas de versioning (deprecated fields)
Breaking changesNouvelle version de l'APIMarquer champ comme @deprecated

REST : quand vous changez la structure, vous créez une nouvelle version.

// Ancienne API
GET /api/v1/users → { "name": "John Doe" }

// Nouvelle API (breaking change)
GET /api/v2/users → { "firstName": "John", "lastName": "Doe" }

GraphQL : vous ajoutez de nouveaux champs sans casser l'ancien.

type User {
  name: String @deprecated(reason: "Use firstName and lastName")
  firstName: String
  lastName: String
}

4. Caching

AspectRESTGraphQL
Caching HTTP✅ Natif (GET cacheable)❌ POST non cacheable par défaut
Caching applicatifRedis, MemcachedApollo Client, Relay (côté client)

REST : cache HTTP standard (ETag, Cache-Control)

GET /api/users/123
Cache-Control: max-age=3600
ETag: "abc123"

GraphQL : nécessite caching applicatif (Apollo Client, DataLoader)

// Apollo Client cache automatiquement par ID
const { data } = useQuery(GET_USER, {
  variables: { id: "123" },
  fetchPolicy: "cache-first"
});

5. Performances

ScénarioRESTGraphQL
Requête simple✅ Rapide⚠️ Légèrement plus lent (parsing)
Données imbriquées❌ Plusieurs requêtes (lent)✅ Une requête (rapide)
Mobile/3G❌ Overfetching = bande passante✅ Données précises

6. Sécurité

RisqueRESTGraphQL
Rate limiting✅ Par endpoint⚠️ Complexe (par query depth)
Attaques DOS✅ Limité par endpoint❌ Requêtes complexes imbriquées
Autorisation✅ Par route⚠️ Par champ (plus granulaire mais complexe)

Problème GraphQL : requêtes malveillantes

// Requête qui peut tuer le serveur
query {
  users {
    posts {
      comments {
        author {
          posts {
            comments {
              author {
                # ... infiniment imbriqué
              }
            }
          }
        }
      }
    }
  }
}

➡️ Solutions : query depth limit, query complexity limit, persistent queries


Exemples de code : Implémentation


API REST avec Express (Node.js)

// server.js
const express = require('express');
const app = express();

app.use(express.json());

// GET /users
app.get('/users', async (req, res) => {
  const users = await db.query('SELECT * FROM users');
  res.json(users);
});

// GET /users/:id
app.get('/users/:id', async (req, res) => {
  const user = await db.query('SELECT * FROM users WHERE id = ?', [req.params.id]);
  if (!user) return res.status(404).json({ error: 'User not found' });
  res.json(user);
});

// POST /users
app.post('/users', async (req, res) => {
  const { name, email } = req.body;
  const result = await db.query('INSERT INTO users (name, email) VALUES (?, ?)', [name, email]);
  res.status(201).json({ id: result.insertId, name, email });
});

// PUT /users/:id
app.put('/users/:id', async (req, res) => {
  const { name, email } = req.body;
  await db.query('UPDATE users SET name = ?, email = ? WHERE id = ?', [name, email, req.params.id]);
  res.json({ id: req.params.id, name, email });
});

// DELETE /users/:id
app.delete('/users/:id', async (req, res) => {
  await db.query('DELETE FROM users WHERE id = ?', [req.params.id]);
  res.status(204).send();
});

app.listen(3000, () => console.log('REST API sur port 3000'));

API GraphQL avec Apollo Server

// server.js
const { ApolloServer, gql } = require('apollo-server');

// 1. Définir le schema
const typeDefs = gql`
  type User {
    id: ID!
    name: String!
    email: String!
    posts: [Post!]!
  }

  type Post {
    id: ID!
    title: String!
    content: String!
    author: User!
    comments: [Comment!]!
  }

  type Comment {
    id: ID!
    content: String!
    author: User!
  }

  type Query {
    users: [User!]!
    user(id: ID!): User
    posts: [Post!]!
  }

  type Mutation {
    createUser(name: String!, email: String!): User!
    createPost(title: String!, content: String!, authorId: ID!): Post!
  }
`;

// 2. Définir les resolvers
const resolvers = {
  Query: {
    users: () => db.query('SELECT * FROM users'),
    user: (_, { id }) => db.query('SELECT * FROM users WHERE id = ?', [id]),
    posts: () => db.query('SELECT * FROM posts'),
  },

  Mutation: {
    createUser: async (_, { name, email }) => {
      const result = await db.query('INSERT INTO users (name, email) VALUES (?, ?)', [name, email]);
      return { id: result.insertId, name, email };
    },
    createPost: async (_, { title, content, authorId }) => {
      const result = await db.query('INSERT INTO posts (title, content, author_id) VALUES (?, ?, ?)',
        [title, content, authorId]);
      return { id: result.insertId, title, content, authorId };
    },
  },

  User: {
    posts: (user) => db.query('SELECT * FROM posts WHERE author_id = ?', [user.id]),
  },

  Post: {
    author: (post) => db.query('SELECT * FROM users WHERE id = ?', [post.author_id]),
    comments: (post) => db.query('SELECT * FROM comments WHERE post_id = ?', [post.id]),
  },

  Comment: {
    author: (comment) => db.query('SELECT * FROM users WHERE id = ?', [comment.author_id]),
  },
};

// 3. Créer le serveur
const server = new ApolloServer({ typeDefs, resolvers });

server.listen(4000).then(({ url }) => {
  console.log(`GraphQL API sur ${url}`);
});

Cas d'usage : Quand utiliser REST ou GraphQL ?


✅ Utilisez REST si :

  • API publique simple : CRUD basique, peu de relations complexes
  • Caching HTTP important : CDN, cache navigateur essentiel
  • Équipe peu expérimentée : REST est plus simple à comprendre
  • Microservices : communication inter-services (REST/gRPC)
  • Standards requis : certains secteurs exigent REST
  • Rate limiting simple : par endpoint

Exemples :

  • API de paiement (Stripe-like)
  • API météo
  • API de géolocalisation
  • Webhook endpoints

✅ Utilisez GraphQL si :

  • Données fortement relationnelles : relations complexes (réseaux sociaux, e-commerce)
  • Multiples clients : web, mobile, IoT avec besoins différents
  • Développement rapide : évolution fréquente du frontend
  • Optimisation mobile : réduire la bande passante
  • Agrégation de données : fusionner plusieurs sources
  • Real-time : subscriptions GraphQL pour WebSocket

Exemples :

  • Réseaux sociaux (Facebook, Instagram, Twitter)
  • Dashboard analytics (données multiples sources)
  • E-commerce (produits + avis + stock + recommandations)
  • SaaS complexe (Notion-like, Linear-like)

Tableau récapitulatif : REST vs GraphQL

CritèreRESTGraphQLGagnant
Simplicité✅ Simple⚠️ Courbe d'apprentissageREST
Flexibilité client❌ Rigide✅ Très flexibleGraphQL
Overfetching❌ Problème✅ RésoluGraphQL
Underfetching❌ Problème (N+1)✅ RésoluGraphQL
Caching HTTP✅ Natif❌ ComplexeREST
Versioning❌ Nécessaire✅ Pas besoinGraphQL
Rate limiting✅ Simple❌ ComplexeREST
Documentation⚠️ Externe (Swagger)✅ Auto-généréeGraphQL
Tooling✅ Mature (Postman, etc.)✅ Excellent (GraphQL Playground)Égalité
Adoption✅ Universelle⚠️ CroissanteREST

Hybride : Peut-on utiliser les deux ?

Oui ! De nombreuses entreprises utilisent les deux :

  • REST pour les endpoints publics simples (webhooks, auth)
  • GraphQL pour les applications clientes riches (dashboard, mobile app)

Exemple : GitHub

  • API REST v3 : https://api.github.com/users/octocat
  • API GraphQL v4 : https://api.github.com/graphql

Tendances 2025

  • REST reste majoritaire : 70% des APIs publiques
  • GraphQL en forte croissance : +40% adoption depuis 2020
  • tRPC émerge : alternative TypeScript-native pour full-stack apps
  • gRPC pour microservices : plus rapide que REST/GraphQL

Conclusion : Quel choix faire en 2025 ?

Il n'y a pas de réponse universelle. Voici la recommandation selon votre contexte :

Choisissez REST si :

  • ✅ Vous débutez ou avez une équipe junior
  • ✅ API publique simple (CRUD basique)
  • ✅ Caching HTTP critique (CDN, edge caching)
  • ✅ Microservices avec communication simple

Choisissez GraphQL si :

  • ✅ Données fortement relationnelles (réseaux sociaux, CMS)
  • ✅ Multiples clients avec besoins différents (web + mobile + IoT)
  • ✅ Optimisation bande passante critique (mobile, IoT)
  • ✅ Développement rapide avec itérations fréquentes

Utilisez les deux si :

  • ✅ Grande application avec besoins variés
  • ✅ Migration progressive (REST → GraphQL)
  • ✅ API publique (REST) + dashboard interne (GraphQL)

En 2025, GraphQL est mature et production-ready. Des géants comme Facebook, Twitter, GitHub, Shopify, Netflix l'utilisent massivement. Mais REST reste pertinent pour de nombreux cas d'usage et ne va pas disparaître.

Commencez simple (REST), migrez vers GraphQL si le besoin émerge. 🚀