3 paradigmes dominent API design en 2026 : tRPC (full-TypeScript), GraphQL (query language flexible), REST (universel). Chacun a son sweet-spot. Le choix impacte vélocité dev, maintenance, performance.
TL;DR
- tRPC : full-TypeScript, type-safety end-to-end, plus rapide dev.
- GraphQL : flexibility max, ressources multiples, mobile-friendly.
- REST : universel, cache HTTP standard, mature.
Comparatif détaillé
| Critère | tRPC | GraphQL | REST |
|---|---|---|---|
| Type safety | 100 % auto | Avec codegen | Manuelle |
| Stack | TS frontend + backend | Quelconque | Quelconque |
| Setup | Très rapide | Moyen | Rapide |
| Over-fetching | Pas | Non | Possible |
| Under-fetching | Pas | Non | Possible (n+1) |
| Caching CDN | Limité | Limité | Excellent |
| Real-time | Subscriptions OK | Subscriptions natif | Webhooks/SSE |
| Versioning | Builds-in | Schema versioning | URL versioning |
| Lock-in | Élevé (TS only) | Moyen | Aucun |
| Tooling | Bon | Excellent | Excellent |
Quand choisir tRPC
Cas idéaux :
- App Next.js + TypeScript end-to-end
- Petite équipe (1-10 dev)
- Pas de mobile app séparée
- Pas d'intégrations third-party majeures
Avantages :
- Type safety 100 % auto (changement schema → erreur compile UI)
- Pas de codegen
- Setup 30 minutes
- Refactoring trivial
`ts
// server/routers/posts.ts
import { z } from 'zod';
import { router, publicProcedure } from '../trpc';
export const postsRouter = router({
list: publicProcedure
.input(z.object({ limit: z.number().default(10) }))
.query(async ({ input, ctx }) => {
return ctx.prisma.post.findMany({ take: input.limit });
}),
create: publicProcedure
.input(z.object({ title: z.string(), content: z.string() }))
.mutation(async ({ input, ctx }) => {
return ctx.prisma.post.create({ data: input });
}),
});
`
`tsx
// Dans component React
import { trpc } from '@/utils/trpc';
export function PostList() {
const { data: posts, isLoading } = trpc.posts.list.useQuery({ limit: 20 });
if (isLoading) return
return posts.map(p =>
}
export function NewPostForm() {
const create = trpc.posts.create.useMutation();
return (
e.preventDefault();
const formData = new FormData(e.currentTarget);
await create.mutateAsync({
title: formData.get('title') as string,
content: formData.get('content') as string,
});
}}>
{/* form fields */}
);
}
`
Tout type-safe. Refactor backend = erreur compile sur frontend instantanément.
Quand choisir GraphQL
Cas idéaux :
- Multi-clients (web + mobile + tablet)
- Queries variées par client (mobile veut moins data)
- Backend public consommé par third-parties
- Complex data graphs (e-commerce avec produits + reviews + variantes)
Avantages :
- Client décide ce qu'il veut récupérer
- Single endpoint pour tout
- Excellent tooling (GraphiQL, Apollo Studio, Codegen)
- Schema first design
`graphql
# schema.graphql
type Post {
id: ID!
title: String!
content: String!
author: User!
comments: [Comment!]!
}
type Query {
posts(limit: Int = 10): [Post!]!
post(id: ID!): Post
}
type Mutation {
createPost(title: String!, content: String!): Post!
}
`
`ts
// resolver
const resolvers = {
Query: {
posts: async (_, { limit }, ctx) => {
return ctx.prisma.post.findMany({ take: limit });
},
Besoin d'un site web professionnel ?
Kolonell crée des sites web qui attirent des clients, optimisés pour le marché sénégalais. Devis gratuit en 2 minutes.
},
Mutation: {
createPost: async (_, { title, content }, ctx) => {
return ctx.prisma.post.create({ data: { title, content } });
},
},
};
`
`tsx
// Client (avec codegen)
const { data } = useGetPostsQuery({ variables: { limit: 20 } });
`
Quand choisir REST
Cas idéaux :
- API publique consommée par many third-parties
- Caching CDN agressif (Cloudflare, Fastly)
- Mobile native (iOS Swift, Android Kotlin) où GraphQL setup lourd
- Compliance / audit trails standardisés
- Microservices polyglot
Avantages :
- Cache HTTP standard (Cache-Control, ETag)
- Tooling universel (Postman, curl)
- Pas de lock-in framework
- Simple à comprendre pour third-parties
- Mature DDoS protection (Cloudflare)
`ts
// Next.js API route
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const limit = parseInt(searchParams.get('limit') ?? '10');
const posts = await prisma.post.findMany({ take: limit });
return Response.json(posts, {
headers: {
'Cache-Control': 'public, max-age=60, stale-while-revalidate=300',
},
});
}
export async function POST(request: Request) {
const data = await request.json();
const post = await prisma.post.create({ data });
return Response.json(post, { status: 201 });
}
`
Pattern hybride recommandé 2026
`
[Frontend Next.js (interne)] ←→ [tRPC]
↑
[Mobile app native] ←→ [REST API]
↑
[Partner intégrations] ←→ [REST API]
↑
[Public OAuth API] ←→ [REST API + GraphQL optional]
`
Une app moderne 2026 expose souvent 2 surfaces :
- tRPC pour Next.js frontend (vélocité)
- REST pour intégrations externes (compatibilité)
Cas réel — SaaS Dakar
Architecture choisie :
- Frontend Next.js + tRPC (équipe interne, refactoring rapide)
- Webhooks Stripe/Wave reçus via API routes REST
- Public API REST pour 8 partenaires intégrés
- Pas de GraphQL (pas de mobile native)
Résultat : -50 % temps dev API vs full-REST + Type safety 100 %.
Performance comparée
- Test : list 50 posts avec author + 5 comments chacun
REST (n+1 problem) :
- 1 GET /posts
- 50 GET /users/{id}
- 50 GET /posts/{id}/comments
- Total : 101 requests, 800ms
REST (with includes/embed) :
- 1 GET /posts?include=author,comments
- Total : 1 request, 250ms
GraphQL :
- 1 POST /graphql avec query
- Total : 1 request, 200ms
- tRPC (Prisma includes) :
- 1 POST /trpc/posts.list
- Total : 1 request, 220ms
GraphQL et tRPC évitent n+1 nativement. REST nécessite design careful (includes, embed).
Pièges fréquents
tRPC
- Pas typescript backend — tRPC require TS strict end-to-end.
- Public API consommée externes — tRPC pas idéal, lock-in.
- Cache CDN — limité, pas standard HTTP cache.
GraphQL
- N+1 dans resolvers — utiliser DataLoader (Facebook).
- Over-engineered pour app simple — GraphQL = complexity overhead.
- Cache CDN difficile — single endpoint, request-based.
REST
- Over-fetching — design bad si /users renvoie 50 fields quand 3 nécessaires.
- N+1 problem — toujours offrir ?include=relations.
- Versioning — /v1, /v2 propre dès le départ.
FAQ
Q : Server Actions remplacent tRPC ?
R : Pour Next.js seul, oui souvent. tRPC reste pertinent si backend séparé (Express, Hono).
Q : GraphQL Federation 2026 ?
R : Apollo Federation pour microservices stay relevant. Mais complexity haute.
Q : Migration ?
R : tRPC → REST/GraphQL : rewrite. REST → GraphQL : possible incrémental.
Conclusion
Choix API 2026 :
- Next.js mono-app + TS : tRPC (ou Server Actions)
- Multi-clients + complex data : GraphQL
- Public API + intégrations : REST
Pattern hybride dominant : tRPC interne + REST externe. Pas de winner unique.
Mohamed Bah
Fondateur, Kolonell
Passionné par le digital et l'entrepreneuriat en Afrique, Mohamed accompagne les entreprises sénégalaises dans leur transformation digitale depuis 2020. Fondateur de Kolonell, il croit que chaque PME mérite une présence en ligne professionnelle et accessible.
