3 points par vtrapplepie 3 시간 전 | Aucun commentaire pour le moment. | Partager sur WhatsApp

Si vous avez déjà vraiment construit un backend en Rust, vous vous êtes probablement heurté au moins une fois à ce mur. Au moment où une base de données devient nécessaire, quatre bibliothèques vous fixent droit dans les yeux, chacune portée par sa propre philosophie, ses compromis, et sa cohorte d’adeptes sur Reddit.

Moi aussi. Au cours de l’année passée, j’ai déployé en production Diesel, SQLx, SeaORM et Rusqlite. Certains choix se sont révélés pertinents, et si c’était à refaire, j’en choisirais d’autres. Certaines choses ont été franchement surprenantes.

Pas de discours marketing, ni de faux-fuyants du style « ça dépend du contexte ». Voici le retour honnête de quelqu’un qui a utilisé les quatre dans du vrai code en production.


En 2026, pourquoi faire du travail DB en Rust ?

Commençons par évacuer cette question. Pourquoi ne pas utiliser SQLAlchemy en Python ou Prisma en Node ?

Pour une application centrée sur la base de données, trois raisons poussent à choisir Rust.

La sécurité à la compilation est ici d’un tout autre niveau. Certaines de ces bibliothèques vérifient littéralement les requêtes SQL à la compilation en les comparant au schéma de la base. Une faute de frappe dans un nom de colonne ? Le compilateur l’attrape. Un type incompatible dans une clause WHERE ? C’est filtré avant même l’exécution du code. Je ne soulignerai jamais assez combien cela réduit les sessions de debug à 3 heures du matin.

L’asynchrone a enfin mûri. Il y a encore quelques années, l’accès DB asynchrone en Rust était rude. Il fallait se battre avec le borrow checker, jongler avec les durées de vie, et composer avec des bibliothèques inabouties. En 2026 ? Ça fonctionne, tout simplement. Tokio est solide, et les bibliothèques ont trouvé leur voie.

On n’a pas à se soucier des performances. La surcharge d’un ORM ne grignote pas votre budget par requête. Le garbage collector ne suspend pas tout au milieu d’une transaction. Les requêtes s’exécutent, les résultats reviennent, et la mémoire est libérée de façon déterministe. Ça marche presque trop bien, au point d’en devenir ennuyeux.


Les quatre prétendants

Voyons-les avec leurs versions les plus récentes, en date de février 2026.

  • Diesel (v2.3.6, janvier 2026) — ORM complet avec SQL à la compilation
  • SQLx (v0.8.6, stable actuelle) — boîte à outils SQL asynchrone (pas un ORM)
  • SeaORM (v2.0, janvier 2026) — ORM dynamique pensé d’abord pour l’asynchrone
  • Rusqlite (v0.38.0, décembre 2025) — wrapper SQLite léger

Ce sont des outils fondamentalement différents qui résolvent des problèmes proches. Voyons-les un par un.


Diesel : celui qui attrape les bugs avant vous

Le meilleur cas d’usage : les équipes qui veulent maximiser la sécurité à la compilation et qui ont un schéma relativement stable

Diesel existe depuis 2015. Dans l’univers Rust, c’est presque l’Antiquité. Et cette maturité se voit, dans le meilleur sens du terme.

L’idée centrale est simple : si le code Diesel compile, le SQL est valide. Ce n’est pas une formule marketing, c’est littéralement son fonctionnement. Diesel génère des types Rust à partir du schéma DB, puis le compilateur vérifie chaque requête que vous écrivez par rapport à ces types.

Pourquoi Diesel continue de me séduire

La validation à la compilation est addictive. Une fois qu’on a vu « le compilateur a détecté un mauvais JOIN avant même que les tests ne tournent », revenir à du SQL piloté par des chaînes de caractères paraît téméraire. Le mois dernier, j’ai refactoré un schéma — renommé trois colonnes et changé des types — et Diesel m’a montré, à la compilation, absolument toutes les requêtes à corriger. Toutes. Sans exception.

L’abstraction zero-cost n’est pas un slogan. Le SQL produit par Diesel est essentiellement identique à celui qu’on écrirait à la main. J’ai comparé les plans d’exécution : ils étaient les mêmes. On obtient la sécurité d’un ORM et les performances du raw SQL.

Les migrations sont bien faites. Ça peut sembler être un standard minimum, mais après avoir combattu avec les outils de migration d’autres écosystèmes, le système de migration de Diesel paraît rafraîchissant de robustesse. Créer, exécuter, annuler — ça marche, point.

Les inconvénients, honnêtement

L’asynchrone a été ajouté après coup, il n’est pas natif. Diesel lui-même est synchrone. Pour faire de l’asynchrone, il faut diesel-async, qui fonctionne bien, mais ajoute une dépendance de plus et une charge mentale supplémentaire. Quand on vient de l’asynchrone natif de SQLx ou SeaORM, ça se remarque.

La courbe d’apprentissage est raide. Le système de types de Diesel est puissant, et ce qui est puissant est complexe. Quand une requête est ratée, l’erreur du compilateur est techniquement exacte, mais elle peut aussi ressembler à 40 lignes de vomi de types génériques. On finit par apprendre à les lire, mais la première semaine est rude.

Les requêtes dynamiques sont pénibles. Si vous devez construire à l’exécution des requêtes dont la structure change — par exemple un endpoint de recherche avec des filtres optionnels — Diesel résiste. Il préfère des formes de requêtes statiques. Dès que la requête devient dynamique, on passe plus de temps à lutter contre le système de types qu’à écrire la logique métier.

Quand choisir Diesel

  • Le projet utilise PostgreSQL ou MySQL et le schéma ne change pas chaque semaine
  • La sécurité à la compilation est non négociable
  • Le code doit survivre des années en production et la correction est cruciale
  • C’est l’option par défaut s’il n’y a pas de raison de faire autrement

SQLx : si vous écrivez du SQL, la sécurité vient en bonus

Le meilleur cas d’usage : les développeurs SQL-first qui veulent la validation à la compilation sans apprendre de DSL

Soyons clairs. SQLx n’est pas un ORM. Il ne génère pas les requêtes et ne gère pas les relations. C’est une boîte à outils SQL. Mais beaucoup de gens l’utilisent à la place d’un ORM, et honnêtement ? Sur de nombreux projets, c’est un meilleur choix.

La magie fonctionne ainsi : vous écrivez vos requêtes raw SQL sous forme de chaînes. SQLx se connecte à une vraie base à la compilation pour les valider. Table inexistante, nom de colonne erroné, type incompatible ? Erreur de compilation. Vous obtenez une sécurité proche de Diesel tout en écrivant du SQL normal.

Ce que SQLx fait vraiment très bien

Si vous connaissez SQL, vous connaissez SQLx. Il n’y a pas de DSL de requête à apprendre. Pas de nouveau modèle mental. Vous écrivez le SQL que vous connaissez déjà, vous ajoutez un peu de macros, et le compilateur s’occupe du reste. D’après mon expérience, intégrer un développeur junior sur un projet SQLx prend quelques heures. Pas quelques jours.

Asynchrone dès le premier jour. SQLx a été conçu pour le Rust asynchrone. Que vous utilisiez Tokio ou async-std, vous choisissez votre runtime et c’est tout. Pas de crate séparée, pas de couche de compatibilité. C’est exactement comme ça que l’accès DB asynchrone devrait fonctionner.

QueryBuilder gère les requêtes dynamiques. C’est là que SQLx bat discrètement Diesel. Besoin d’un endpoint de recherche où l’utilisateur peut filtrer selon n’importe quelle combinaison de 12 champs ? Le QueryBuilder de SQLx permet de construire ce genre de requêtes dynamiques de façon intuitive. Même construites par morceaux, elles restent paramétrées et donc protégées contre les injections.

Les inconvénients, honnêtement

La base doit être disponible pendant la compilation. C’est l’aspect le plus controversé de SQLx. Le pipeline CI a besoin d’un accès DB, et un nouveau développeur doit lancer la base avant de compiler. Le mode hors ligne permet de mettre en cache les métadonnées des requêtes, mais cela ajoute une étape de workflow qu’il faut penser à suivre.

Il n’y a pas de fonctionnalités ORM de haut niveau. Pas de chargement de relations. Pas de eager/lazy loading. Pas de JOIN automatiques. Si vous avez un modèle de données complexe avec des relations imbriquées, il faudra écrire tout le SQL à la main. Pour du CRUD simple, c’est très bien. Pour des graphes de données complexes, cela devient fastidieux.

Le mode hors ligne demande de la discipline. Pour construire sans base, il faut générer les fichiers .sqlx avec cargo sqlx prepare. Ces fichiers contiennent les métadonnées de requête mises en cache. Si vous modifiez une requête et oubliez de les régénérer ? Vous obtenez un build obsolète. Ça fonctionne, mais avec un peu de friction.

Quand choisir SQLx

  • L’équipe pense déjà en SQL et ne veut pas de couche d’abstraction
  • Les requêtes dynamiques sont une exigence clé
  • Vous démarrez un nouveau projet et voulez le chemin le plus court vers un code DB fonctionnel
  • Vous avez besoin d’un accès DB asynchrone sans compromis

SeaORM : celui qui paraît familier

Le meilleur cas d’usage : les développeurs qui veulent une expérience ORM moderne avec asynchrone et requêtes dynamiques

Si vous avez déjà utilisé Django ORM, ActiveRecord ou Eloquent, SeaORM vous semblera familier. Et à partir de la version 2.0 sortie en janvier 2026, c’est vraiment prêt pour la production.

SeaORM adopte l’approche exactement opposée à Diesel. Au lieu de vérifier à la compilation, il fonctionne à l’exécution. On perd un peu en sécurité, mais on gagne une flexibilité que les autres bibliothèques ne peuvent pas égaler.

Pourquoi SeaORM 2.0 mérite l’attention

Les relations fonctionnent comme on l’attend. Un-à-plusieurs, plusieurs-à-plusieurs, eager loading, lazy loading — SeaORM gère tout cela. Si vous avez un modèle de données complexe avec utilisateurs, posts, commentaires et tags, SeaORM permet de naviguer naturellement dans ces relations. On n’a pas l’impression de se battre contre la base.

Les requêtes dynamiques sont des citoyennes de première classe. Filtres optionnels ? Tri conditionnel ? Pagination ? SeaORM gère tout cela sans effort conscient. Son query builder fonctionne à l’exécution, donc la structure peut changer librement. C’est là où Diesel souffre et où SeaORM brille.

Les fonctionnalités de la 2.0 sont réellement utiles. Entity Loader résout élégamment le problème du N+1 — il charge efficacement les entités liées par lots au lieu de lancer des requêtes séparées. sea-orm-sync fournit une variante synchrone pour les outils CLI et les scripts. Nested ActiveModel rend les insertions complexes plus propres.

La génération d’entités fait vraiment gagner du temps. Vous pointez sea-orm-cli vers une base, et il génère les entités Rust. Le schéma change ? Il suffit de régénérer. Ce n’est pas un travail glamour, mais l’automatiser réduit les bugs liés à l’écriture manuelle des structs.

Les inconvénients, honnêtement

Les erreurs à l’exécution existent réellement. Contrairement à Diesel ou SQLx, SeaORM n’attrape pas les divergences de schéma à la compilation. Vous renommez une colonne et oubliez de mettre à jour une entité ? Erreur à l’exécution. Il faut compenser cela par une bonne couverture de tests.

C’est relativement récent. SeaORM 2.0 est stable, mais son écosystème reste plus petit. Il y a moins de billets de blog, moins de réponses sur Stack Overflow, moins de discussions du type « j’ai eu exactement le même problème ». Vous dépendrez davantage de la documentation officielle et du Discord.

Un léger surcoût à l’exécution. Construire dynamiquement les requêtes a un prix. Il est faible — négligeable pour 99 % des applications — mais si vous traquez chaque microseconde, Diesel ou SQLx seront plus rapides.

Quand choisir SeaORM

  • Vous construisez une API web avec des relations complexes entre entités
  • La recherche dynamique et le filtrage sont des fonctionnalités majeures
  • L’équipe vient de Django, Rails ou Laravel et veut des patterns familiers
  • La vitesse de développement compte plus que les garanties à la compilation

Rusqlite : le choix évident (pour SQLite)

Le meilleur cas d’usage : outils CLI, applications desktop, systèmes embarqués, et tout ce qui utilise SQLite

Appeler Rusqlite un « ORM » serait généreux. C’est un wrapper autour de SQLite. Mais c’est précisément là sa force : il fait une seule chose, et la fait parfaitement.

Si votre projet utilise SQLite — et c’est le cas de beaucoup de projets Rust — Rusqlite est un choix évident, sans réelle contestation possible.

Pourquoi Rusqlite fonctionne tout simplement

Le SQLite embarqué est fantastique. Avec le feature flag bundled, Rusqlite compile SQLite directement dans le binaire. Pas de dépendances système. Pas de « veuillez installer sqlite3-dev ». Le binaire tourne partout. J’ai déjà déployé des outils CLI sur des machines complètement nues : ça a fonctionné immédiatement.

C’est correctement minimal. Rusqlite n’essaie pas d’être malin. Il fournit des connexions, des prepared statements et des transactions, puis ajoute par-dessus la sécurité de types de Rust. Le borrow checker empêche les mauvais usages des ressources. Les prepared statements empêchent l’injection. Et c’est tout. C’est toute la bibliothèque.

Les fonctionnalités spécifiques à SQLite sont exposées. Fonctions SQL personnalisées, tables virtuelles, recherche plein texte, extension JSON — Rusqlite vous donne accès à tout l’éventail des possibilités de SQLite. Un ORM générique a tendance à les cacher derrière une abstraction. Rusqlite vous laisse les utiliser directement.

Les inconvénients, honnêtement

Ça ne fonctionne qu’avec SQLite. Si vous avez besoin de PostgreSQL ou MySQL, Rusqlite n’est pas votre bibliothèque. Fin de la discussion.

Il n’y a aucune commodité d’ORM. Pas de query builder. Pas de gestion des relations. Pas de migrations (même si vous pouvez bien sûr utiliser refinery ou rusqlite_migration). Vous écrivez les chaînes SQL vous-même et mappez manuellement les résultats.

C’est uniquement synchrone. Rusqlite ne fait pas d’asynchrone. Pour un outil CLI ou une application desktop, ce n’est généralement pas un problème. Pour un serveur web, il vaut mieux utiliser le support SQLite de SQLx ou l’envelopper dans un thread pool.

Quand choisir Rusqlite

  • Vous créez un outil CLI qui a besoin de stockage local
  • Vous développez une application desktop avec base embarquée
  • Votre projet est de ceux pour lesquels SQLite est le bon choix de base de données
  • Vous déployez dans un environnement où il est impossible d’installer un serveur DB

Comment je tranche en pratique

Après avoir utilisé les quatre en production, voici le cadre mental que j’applique.

C’est du SQLite ? → Rusqlite. Fin. N’y réfléchissez pas davantage.

Vous voulez la validation SQL à la compilation + un DSL de requête ? → Diesel. C’est le pari le plus sûr pour une base de code faite pour durer.

Vous voulez la validation à la compilation mais préférez écrire du raw SQL ? → SQLx. Toute la sécurité, sans la courbe d’apprentissage d’un DSL.

Vous avez besoin de requêtes dynamiques, de relations, et d’un ORM asynchrone moderne ? → SeaORM 2.0. Surtout si vous venez de Django ou Rails.

Le choix par défaut sur un nouveau projet ? → En général, je commence avec Diesel. Sauf bonne raison de faire autrement. La sécurité à la compilation m’a sauvé trop de fois.


La vérité inconfortable

Il y a une chose que personne dans la communauté Rust ne veut vraiment admettre : pour la plupart des projets, n’importe laquelle de ces options fera correctement le travail.

Elles sont toutes bien maintenues. Elles empêchent toutes l’injection SQL. Elles fonctionnent toutes avec les bases qui comptent dans leur périmètre respectif. Les différences se jouent surtout à la marge, et la plupart d’entre nous ne vivent pas à cette marge.

Choisissez celle qui correspond à votre façon de penser. Si vous raisonnez en SQL, prenez SQLx. Si vous voulez que le compilateur veille sur vous, prenez Diesel. Si vous cherchez quelque chose qui ressemble à l’ORM que vous connaissez déjà, prenez SeaORM. Si c’est du SQLite, prenez Rusqlite.

Et maintenant, arrêtez de faire de la recherche et commencez à builder.

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.