0

Benchmark Django Ninja vs DRF : Analyse critique et nouveaux résultats


Hello les devs 👋,

Récemment, je me suis penché sur le cas de Django Ninja, ce nouveau challenger qui promet d’apporter la vitesse de FastAPI à l’écosystème Django.

Sur le papier, les benchmarks sont impressionnants. Mais en y regardant de plus près, j’ai eu l’impression que la comparaison était un peu… biaisée. 🤔

En effet, les benchmarks officiels comparent souvent DRF-uwsgi (mode synchrone) avec Django-Ninja-uvicorn (mode asynchrone). C’est un peu comme comparer une voiture de course sur une autoroute avec un 4x4 sur un chemin de terre. Les deux sont performants, mais ils ne courent pas dans la même catégorie.

J’ai donc décidé de réaliser mes propres tests de performance en local pour remettre les pendules à l’heure. ⏱️

🧪 La méthodologie de test

Pour avoir une comparaison équitable, j’ai réalisé plusieurs scénarios de tests en isolant les variables.

L’idée est de comparer :

  1. Sync vs Sync : DRF sous uWSGI vs Ninja sous uWSGI.
  2. Validation d’input : DRF Serializers vs Pydantic (utilisé par Ninja).
  3. Async : Voir comment tout ce petit monde se comporte avec des appels asynchrones.

J’ai utilisé le repo suivant comme base (modifié pour les besoins du test) : https://github.com/vitalik/django-ninja-benchmarks/tree/master

Les configurations testées :

  • DRF-uwsgi (Sync) : La stack classique et robuste.
  • Ninja-uwsgi (Sync) : Ninja utilisé de manière synchrone.
  • DRF-uvicorn (Async) : DRF tournant sous un serveur ASGI.
  • Ninja-uvicorn (Async) : La configuration “star” mise en avant.

📊 Les Résultats

Voici ce que j’ai constaté après avoir lancé les tests sur ma machine.

1. Appels API avec la lib Requests (Client Synchrone)

Comparaison : DRF-uwsgi (sync) Vs Ninja-uwsgi (sync)

Dans ce scénario classique (un client type script python standard), on compare les deux frameworks sur un pied d’égalité (WSGI).

Benchmark Sync Requests

👉 Résultat : Sans surprise, Django Ninja prend l’avantage grâce à sa légèreté, mais l’écart est moins abyssal que lorsqu’on change de serveur d’application. DRF reste tout à fait capable, mais la validation Pydantic de Ninja lui donne un boost.

2. Appels API avec la lib Aiohttp (Client Asynchrone)

Comparaison : DRF-uwsgi Vs Ninja-uwsgi Vs DRF-uvicorn Vs Ninja-uvicorn

Ici, on bombarde le serveur avec des requêtes concurrentes.

Benchmark Async Aiohttp Benchmark Concurrency

👉 Résultat : C’est ici que c’est intéressant. On pourrait penser que le mode Async gagne à tous les coups. Pourtant, sur des opérations simples ou CPU-bound (comme de la sérialisation JSON lourde), Django (en mode Sync uWSGI) se défend incroyablement bien, voire surpasse les versions Async mal configurées.

La gestion des threads par uWSGI est extrêmement mature et performante pour du code Python standard.

3. Validation de JSON en input

Comparaison : DRF Serializer vs Pydantic Schema

C’est souvent le goulot d’étranglement des APIs : valider ce que l’utilisateur envoie.

Benchmark Validation

👉 Résultat : Pydantic (et donc Ninja) écrase DRF. 🚀 Il n’y a pas photo ici. Pydantic est écrit en partie en Rust (dans sa v2) et optimisé à l’extrême. Les Serializers de DRF sont très flexibles et puissants, mais ils sont beaucoup plus lents à l’exécution pure.

Si votre API fait beaucoup de validation de données complexes, Ninja vous fera gagner un temps précieux, quel que soit le serveur (uWSGI ou Uvicorn).


🏆 Le Verdict : Django est le vainqueur 🎉

Ma conclusion est peut-être contre-intuitive, mais voici mon analyse :

Ce n’est pas tant “Ninja vs DRF” ou “Async vs Sync”. Le grand gagnant, c’est l’écosystème Django.

  1. Si vous avez besoin de performance brute de validation : Ninja (Pydantic) est imbattable.
  2. Si vous avez une app existante : Passer à Ninja peut aider, mais optimiser votre serveur WSGI (passer à uWSGI avec les bons réglages de threads/process) est souvent l’optimisation la plus rentable (ROI).
  3. L’asynchrone n’est pas magique : Comme je l’expliquais dans un autre article, l’async ne devient indispensable que sur des I/O très spécifiques (WebSockets, SSE, requêtes HTTP sortantes lentes). Pour du CRUD classique, un Django synchrone bien tuné est une bête de course.

En résumé

Les benchmarks officiels ne mentent pas, mais ils racontent une histoire spécifique (le “happy path” de Ninja). En conditions réelles, à armes égales (Sync vs Sync), Ninja reste plus rapide grâce à Pydantic, mais DRF n’est pas aussi “has-been” qu’on veut bien le dire.

Mon conseil ? Testez par vous-même avec vos propres cas d’usage !

Avez-vous observé les mêmes résultats en prod ? Dites-le-moi sur Twitter ou LinkedIn !

Commentaires