Backends TypeScript Modernes : Hono, ElysiaJS et Ce Qui Vient Après NestJS
Comparaison honnête de Hono, ElysiaJS et NestJS par quelqu'un qui fait tourner les trois en production. DX, performance, middleware, ORM, déploiement et quand choisir chacun.
Pourquoi On Ne Démarre Plus de Nouveaux Projets avec NestJS
NestJS est un excellent framework. On a construit des systèmes enterprise dessus (Vendure tourne sur NestJS sous le capot, et on adore Vendure). Mais pour les nouveaux services backend autonomes, on est passés à Hono. Pas parce que NestJS est mauvais. Parce que Hono correspond mieux à notre façon de travailler maintenant.
Le changement s'est fait progressivement. On a démarré un nouveau service API, envisagé NestJS, et on s'est posé la question : est-ce qu'on a besoin de decorators, modules, providers et du conteneur d'injection de dépendances inspiré d'Angular pour une API de 15 endpoints ? La réponse était non. On avait besoin d'un framework HTTP rapide qui tourne sur n'importe quel runtime, avec un bon support TypeScript, et qui n'impose pas d'architecture.
Hono a répondu à ça. Ensuite on a essayé ElysiaJS sur Bun pour un service critique en performance. Le résultat était différent. Cet article est une comparaison honnête de quelqu'un qui fait tourner les trois en production.
Pour le contexte plus large sur notre approche de l'ingénierie logicielle, ce guide couvre nos principes. Pour voir comment ces frameworks s'intègrent dans l'architecture commerce, consulte notre guide Vendure en production.
Les Trois Frameworks
| Caractéristique | NestJS | Hono | ElysiaJS |
|---|---|---|---|
| Runtime | Node.js | Node, Bun, Deno, Cloudflare Workers, Lambda, Vercel | Bun (principalement) |
| Architecture | Opinionné (modules, controllers, providers) | Minimal (routes, middleware) | Minimal (routes, plugins) |
| Sécurité des types | Decorators + validation runtime | Basé middleware, manuel | Validation intégrée (typebox) |
| Conteneur DI | Intégré (style Angular) | Aucun (à toi de choisir) | Aucun (plugins) |
| Taille du bundle | Large (~50 Mo node_modules) | Minuscule (~14 Ko core) | Petit (~2 Mo avec Bun) |
| Démarrage à froid | Lent (2-5s sur Lambda) | Rapide (< 100ms sur Lambda) | Rapide (< 50ms sur Bun) |
| Écosystème middleware | Large (passport, class-validator, etc.) | En croissance (auth, cors, jwt, etc.) | En croissance (swagger, jwt, etc.) |
| Courbe d'apprentissage | Raide (modules, decorators, DI, guards, pipes) | Minimale (style express) | Minimale (style express avec validation) |
| Idéal pour | Grosses apps enterprise, plugins Vendure | APIs multi-runtime, fonctions edge, microservices | APIs haute performance natives Bun |
Hono : Le Framework Qui Tourne Partout
Hono est un framework web construit pour l'edge. Il tourne sur Node.js, Bun, Deno, Cloudflare Workers, AWS Lambda, Vercel Edge et Fastly. Le même code se déploie sur n'importe quel runtime sans modification.
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { jwt } from 'hono/jwt';
import { logger } from 'hono/logger';
const app = new Hono();
// Middleware
app.use('*', logger());
app.use('*', cors({ origin: ['https://app.example.com'] }));
app.use('/api/*', jwt({ secret: process.env.JWT_SECRET! }));
// Routes
app.get('/api/products', async (c) => {
const products = await productService.findAll();
return c.json({ data: products });
});
app.get('/api/products/:id', async (c) => {
const product = await productService.findById(c.req.param('id'));
if (!product) return c.json({ error: 'Not found' }, 404);
return c.json({ data: product });
});
app.post('/api/products', async (c) => {
const body = await c.req.json();
const product = await productService.create(body);
return c.json({ data: product }, 201);
});
export default app;
Pourquoi On l'Aime
Portabilité runtime. On déploie le même code Hono sur Lambda (API Gateway), Bun (container) et Cloudflare Workers (edge). Aucun changement de code entre les runtimes. C'est la force unique de Hono. Aucun autre framework ne fait ça.
14 Ko de core. Les démarrages à froid sur Lambda sont sous les 100ms. Les démarrages à froid de NestJS font 2 à 5 secondes. Pour les déploiements serverless, cette différence représente toute l'expérience utilisateur.
Aucune opinion sur l'architecture. Hono te donne le routing, le middleware et le contexte. Tu décides comment structurer les services, les repositories et la logique métier. Pour les APIs petites à moyennes (5-50 endpoints), c'est exactement ce qu'il faut. Tu n'as pas besoin d'un système de modules pour 20 routes.
Intégration tRPC. On utilise Hono + tRPC pour les stacks full TypeScript. Sécurité de type de bout en bout, du serveur au client, sans GraphQL :
import { trpcServer } from '@hono/trpc-server';
import { appRouter } from './trpc/router';
app.use('/trpc/*', trpcServer({ router: appRouter }));
Où Ça Pêche
Pas de DI intégré. Pour les grosses applications avec 50+ services et des graphes de dépendances complexes, tu dois ramener ton propre conteneur DI (tsyringe, inversify) ou câbler les dépendances manuellement. C'est suffisant pour les petits services. Ça devient fastidieux pour les gros.
Écosystème middleware plus petit. NestJS a passport, class-validator, class-transformer, swagger et des centaines de packages communautaires. L'écosystème de Hono grandit mais n'en est pas encore là. Tu vas écrire plus de middleware custom.
Pas de conventions pour les grosses apps. Les modules NestJS te donnent une structure qui tient la route avec 100+ fichiers. Hono n'impose aucune structure. Pour les équipes avec des développeurs juniors, l'absence de conventions peut mener à des codebases incohérentes.
ElysiaJS : Quand la Performance Bun Compte
ElysiaJS est construit spécifiquement pour Bun. Il tire parti des APIs natives de Bun, des bindings FFI et du serveur HTTP optimisé pour atteindre des performances que les frameworks Node.js ne peuvent pas égaler.
import { Elysia, t } from 'elysia';
import { swagger } from '@elysiajs/swagger';
import { jwt } from '@elysiajs/jwt';
const app = new Elysia()
.use(swagger())
.use(jwt({ name: 'jwt', secret: process.env.JWT_SECRET! }))
.get('/products', async () => {
return productService.findAll();
})
.post('/products', async ({ body }) => {
return productService.create(body);
}, {
body: t.Object({
name: t.String(),
price: t.Number({ minimum: 0 }),
description: t.Optional(t.String()),
}),
})
.listen(3000);
Pourquoi C'est Intéressant
Validation intégrée avec TypeBox. Les schémas sont définis en inline, et génèrent automatiquement la doc OpenAPI. Pas besoin de bibliothèque de validation séparée. Les types circulent du schéma au handler jusqu'à la réponse.
Performance native Bun. ElysiaJS sur Bun gère 2 à 3 fois plus de requêtes par seconde qu'Express sur Node.js pour les APIs JSON simples. Pour les workloads légers en calcul et lourds en I/O (la majorité des APIs), la différence est moins spectaculaire mais toujours mesurable.
Inférence de type de bout en bout. Le type du body de requête est inféré depuis le schéma TypeBox. Le type de la réponse est inféré depuis le handler. Le client peut utiliser Eden (le client style tRPC d'ElysiaJS) pour des appels API type-safe.
Où Ça Pêche
Bun uniquement. Si tu dois déployer sur Node.js, Lambda ou Cloudflare Workers, ElysiaJS n'est pas une option. Bun est prêt pour la production mais pas universellement supporté dans tous les environnements d'hébergement.
Écosystème plus petit. La compatibilité des packages de Bun est bonne mais pas à 100%. Certains packages Node.js utilisent des addons natifs que Bun ne supporte pas. Les drivers de base de données, les bibliothèques de traitement d'images et certains modules crypto natifs peuvent poser problème.
Moins éprouvé en production. Bun et ElysiaJS sont plus récents. La communauté est plus petite. Quand tu tombes sur un cas limite, il y a moins de réponses Stack Overflow et moins de gens qui ont résolu le même problème.
Drizzle vs Prisma vs TypeORM : La Réalité des ORM
Le choix du framework, c'est la moitié de la décision. Le choix de l'ORM, c'est l'autre moitié.
| Caractéristique | Drizzle | Prisma | TypeORM |
|---|---|---|---|
| Style de requête | SQL-like (explicite) | API client (générée) | Active Record ou Data Mapper |
| Sécurité des types | Excellente (inférée du schéma) | Excellente (client généré) | Bonne (decorators) |
| Migration | SQL, contrôle manuel | Auto-générée, gérée | Auto-générée ou manuelle |
| Performance | Rapide (wrapper fin sur SQL) | Bonne (moteur de requêtes) | Modérée (abstraction lourde) |
| SQL brut | First-class (template sql``) | Possible mais laborieux | Possible via query builder |
| Edge/Serverless | Fonctionne (léger) | Nécessite Prisma Accelerate pour l'edge | Trop lourd pour l'edge |
| Courbe d'apprentissage | Basse (si tu connais le SQL) | Basse (docs API excellentes) | Moyenne (decorators, relations) |
| Taille du bundle | Petit (~500 Ko) | Large (~15 Mo avec moteur) | Moyen (~5 Mo) |
| Idéal avec | Hono, ElysiaJS | N'importe quel framework | NestJS, Vendure |
Nos Choix de Stack
Hono + Drizzle + tRPC : pour les nouvelles APIs TypeScript. Léger, rapide, type-safe de bout en bout. La syntaxe SQL-like de Drizzle nous donne un contrôle explicite sur les requêtes sans l'overhead d'abstraction de TypeORM ni l'overhead moteur de Prisma.
// Drizzle : SQL-like, explicite, type-safe
const products = await db
.select()
.from(productsTable)
.where(and(
eq(productsTable.tenantId, tenantId),
eq(productsTable.status, 'active'),
gt(productsTable.price, 1000),
))
.orderBy(desc(productsTable.createdAt))
.limit(20);
NestJS + TypeORM : pour les plugins Vendure et les grosses applications enterprise où le système de modules et le conteneur DI justifient leur poids. TypeORM s'intègre profondément avec NestJS et Vendure.
Prisma : quand on a besoin de migrations auto-générées et que l'équipe valorise la documentation et la DX de Prisma plutôt que le contrôle brut des requêtes.
Flexibilité de Déploiement
C'est ici que le choix du framework a le plus gros impact pratique.
| Cible de déploiement | NestJS | Hono | ElysiaJS |
|---|---|---|---|
| Docker/Kubernetes | Fonctionne | Fonctionne | Fonctionne (image Bun) |
| AWS Lambda | Démarrages à froid lents (2-5s) | Rapide (< 100ms) | Non supporté |
| Cloudflare Workers | Non supporté | Fonctionne nativement | Non supporté |
| Vercel Edge | Non supporté | Fonctionne nativement | Non supporté |
| Deno Deploy | Non supporté | Fonctionne nativement | Non supporté |
| VPS traditionnel | Fonctionne | Fonctionne | Fonctionne (nécessite Bun) |
| Bun natif | Partiel (la plupart de NestJS tourne sur Bun) | Fonctionne | Natif, optimisé |
Si tu déploies uniquement sur des containers, les trois fonctionnent très bien. Si tu déploies en serverless ou sur l'edge, Hono est le seul framework qui te donne toutes les options. ElysiaJS est limité à Bun. NestJS est limité à Node (en pratique).
Pour savoir comment on déploie les services sur notre infrastructure cloud, y compris Kubernetes, Lambda et les fonctions edge, cette page détaille notre approche.
Quand NestJS Reste le Bon Choix
Malgré notre préférence pour Hono sur les nouveaux projets, NestJS est le bon choix quand :
- Tu construis des plugins Vendure. Vendure EST NestJS. Le système de plugins, les services, les resolvers et les guards utilisent tous les patterns NestJS. Se battre contre le framework est pire que de l'utiliser.
- Ton équipe connaît Angular. Le pattern module/provider/controller de NestJS reflète Angular. Si ton équipe vient d'Angular, la courbe d'apprentissage est quasi nulle.
- Tu as besoin d'un large écosystème middleware. Stratégies Passport, class-validator, génération Swagger automatique, GraphQL code-first. NestJS a tout ça, intégré ou bien connecté.
- L'application va dépasser les 100+ fichiers. Les modules NestJS fournissent une structure qui passe à l'échelle. Sans conventions (Hono, ElysiaJS), les grosses équipes ont besoin de discipline pour maintenir la cohérence.
- Tu as besoin de support WebSocket. NestJS a des gateways WebSocket intégrées avec le même pattern de decorators. Le support WebSocket de Hono est plus manuel.
Pièges Courants
-
Choisir Hono et reconstruire NestJS. Si tu finis par ajouter un conteneur DI, du routing basé sur des decorators, un système de modules et un pattern de guards à Hono, tu as juste construit un NestJS en moins bien. Utilise NestJS.
-
Choisir ElysiaJS pour la production sans évaluer la compatibilité Bun. Vérifie que toutes tes dépendances fonctionnent sur Bun. Les addons natifs, certains drivers de base de données et quelques bibliothèques crypto peuvent ne pas fonctionner.
-
Ignorer les temps de démarrage à froid en serverless. NestJS sur Lambda est inutilisable pour les APIs user-facing sans provisioned concurrency. Hono sur Lambda est assez rapide sans ça.
-
Utiliser TypeORM avec Hono. TypeORM est conçu pour les patterns DI de NestJS. Sans DI, gérer les connexions et repositories TypeORM est laborieux. Utilise Drizzle ou Prisma avec Hono.
-
Changer de framework prématurément. Si ton app NestJS fonctionne et que ton équipe est productive, ne passe pas à Hono juste pour être à la mode. Change quand tu as une raison concrète (déploiement serverless, fonctions edge, nouveau service autonome).
-
Pas de couche de validation. Hono n'inclut pas de validation des requêtes. Utilise un middleware Zod ou construis le tien. Livrer une API sans validation des entrées est une vulnérabilité de sécurité.
Points Clés à Retenir
-
Hono est le framework backend TypeScript le plus polyvalent. 14 Ko de core, tourne sur tous les runtimes, démarrages à froid rapides, aucune opinion sur l'architecture. Notre choix par défaut pour les nouvelles APIs autonomes.
-
ElysiaJS offre la meilleure performance sur Bun. Validation intégrée, excellente DX, type-safe de bout en bout. Mais la limitation à Bun restreint les options de déploiement.
-
NestJS reste le bon choix pour les grosses apps enterprise et Vendure. Modules, DI, guards et un écosystème massif. La courbe d'apprentissage se rentabilise à grande échelle.
-
Drizzle est notre ORM préféré avec Hono. Syntaxe SQL-like, requêtes explicites, bundle léger. Prisma pour les équipes qui préfèrent les clients auto-générés. TypeORM pour NestJS/Vendure.
-
La cible de déploiement conditionne le choix du framework. Le serverless et l'edge nécessitent Hono. Les containers fonctionnent avec tout. Le Bun natif nécessite ElysiaJS.
-
Ne change pas de framework sans raison. Si NestJS fonctionne, continue avec. Change quand tu as besoin de serverless, d'edge, ou d'un nouveau service autonome où l'approche légère est réellement meilleure.
On construit des backends TypeScript sur les trois frameworks dans le cadre de notre pratique de développement web et de logiciel sur mesure. Si tu évalues des frameworks pour un nouveau projet, discute avec notre équipe ou demande un devis.
Sujets couverts
Guides connexes
Guide Entreprise des Systèmes d'IA Agentiques
Guide technique des systemes d'IA agentiques en entreprise. Decouvre l'architecture, les capacites et les applications des agents IA autonomes.
Lire le guideCommerce Agentique : Comment laisser les agents IA acheter en toute securite
Comment concevoir un commerce agentique gouverne. Moteurs de politiques, portes d'approbation HITL, reçus HMAC, idempotence, isolation multi-tenant et le protocole Agentic Checkout complet.
Lire le guideLes 9 endroits où ton système IA laisse fuir des données (et comment colmater chacun)
Cartographie systématique de chaque point de fuite de données dans les systèmes IA. Prompts, embeddings, logs, appels d'outils, mémoire d'agent, messages d'erreur, cache, données de fine-tuning et transferts entre agents.
Lire le guidePrêt à construire des systèmes IA prêts pour la production ?
Notre équipe est spécialisée dans les systèmes IA prêts pour la production. Discutons de comment nous pouvons aider.
Démarrer une conversation