décembre 21, 2025
14 min de lecture

Questions d’entretien Node.js pour backend senior

interview
career-advice
job-search
Questions d’entretien Node.js pour backend senior
Milad Bonakdar

Milad Bonakdar

Auteur

Préparez vos entretiens backend senior Node.js avec 30 questions pratiques sur l’event loop, les streams, la sécurité API, le system design, le passage à l’échelle, la performance, les tests et la production.


Questions d’entretien Node.js pour backend senior

Un entretien senior Node.js évalue rarement la syntaxe seule. Attendez-vous à expliquer votre raisonnement sur l’event loop, la backpressure, les frontières d’API, les systèmes distribués, l’observabilité, la sécurité et les compromis de production. Les meilleures réponses relient les mécanismes internes de Node.js à des décisions prises sur de vrais services.

Utilisez ces 30 questions pour préparer des réponses courtes et solides. Pour chaque thème, préparez un exemple personnel : une décision de mise à l’échelle, un problème de performance, un incident de fiabilité ou un compromis d’architecture que vous pouvez expliquer clairement.


Concepts Avancés de Node.js (10 Questions)

1. Expliquez en détail la boucle d'événements (Event Loop) de Node.js. Quelles sont les différentes phases ?

Réponse : L’event loop permet à Node.js d’exécuter des E/S non bloquantes alors que JavaScript s’exécute par défaut sur un seul thread principal. Le système d’exploitation ou libuv gère le travail en attente, puis les callbacks sont mis en file pour être exécutés par JavaScript.

  • Timers : Exécute les callbacks de setTimeout() et setInterval(). Dans les versions modernes de Node.js, le travail de la phase poll peut influencer le moment d’exécution.
  • Pending callbacks : Exécute certains callbacks d’E/S système différés à l’itération suivante.
  • Idle, prepare : Phases internes de libuv.
  • Poll : Récupère les nouveaux événements d’E/S et exécute les callbacks associés. Si la file est vide, Node.js peut attendre des E/S ou passer à la suite lorsque des callbacks setImmediate() sont prêts.
  • Check : Exécute les callbacks setImmediate().
  • Close callbacks : Exécute les handlers de fermeture comme socket.on('close', ...).

Une réponse senior mentionne aussi les microtasks : process.nextTick() s’exécute avant les promesses, et les deux s’exécutent avant que l’event loop continue. Un usage excessif peut affamer les E/S.

Rareté : Très Courant Difficulté : Difficile


2. Quelle est la différence entre process.nextTick() et setImmediate() ?

Réponse :

  • process.nextTick() : Ne fait pas partie de la boucle d'événements. Il se déclenche immédiatement après la fin de l'opération en cours, mais avant que la boucle d'événements ne continue. Il a une priorité plus élevée que setImmediate(). Une utilisation excessive peut bloquer la boucle d'événements (starvation).
  • setImmediate() : Fait partie de la phase Check de la boucle d'événements. Il s'exécute après la phase Poll.

Rareté : Courant Difficulté : Moyen


3. Comment Node.js gère-t-il la concurrence s'il est monothread ?

Réponse : Node.js utilise un modèle d'E/S non bloquant piloté par les événements.

  • Thread Principal : Exécute le code JavaScript (moteur V8).
  • Libuv : Une bibliothèque C qui fournit la boucle d'événements et un pool de threads (4 threads par défaut).
  • Mécanisme : Lorsqu'une opération asynchrone (comme une E/S de fichier ou une requête réseau) est initiée, Node.js la décharge vers Libuv. Libuv utilise son pool de threads (pour les E/S de fichiers, DNS) ou les mécanismes asynchrones du noyau du système (pour le réseau). Lorsque l'opération est terminée, le rappel est ajouté à la file d'attente de la boucle d'événements pour être exécuté par le thread principal.

Rareté : Courant Difficulté : Moyen


4. Expliquez les flux (Streams) dans Node.js et leurs types.

Réponse : Les flux sont des objets qui vous permettent de lire des données à partir d'une source ou d'écrire des données vers une destination en blocs continus. Ils sont efficaces en termes de mémoire car vous n'avez pas besoin de charger toutes les données en mémoire.

  • Types :
    1. Readable (Lisible) : Pour lire des données (par exemple, fs.createReadStream).
    2. Writable (Écrivable) : Pour écrire des données (par exemple, fs.createWriteStream).
    3. Duplex (Double Sens) : À la fois lisible et écrivable (par exemple, les sockets TCP).
    4. Transform (Transformation) : Flux duplex où la sortie est calculée en fonction de l'entrée (par exemple, zlib.createGzip).

Rareté : Courant Difficulté : Moyen


5. Qu'est-ce que la contre-pression (Backpressure) dans les flux et comment la gérez-vous ?

Réponse : La backpressure apparaît lorsqu’un stream readable produit des données plus vite que la partie writable ne peut les consommer. Si elle est ignorée, les buffers grossissent, le garbage collector travaille davantage et le processus peut manquer de mémoire.

  • Utiliser stream.pipeline() ou pipeline de node:stream/promises : Cela connecte les streams, propage les erreurs et nettoie correctement les ressources.
  • Respecter .write() : Si la méthode renvoie false, attendez l’événement drain avant d’écrire davantage.
  • Ajuster avec prudence : highWaterMark peut aider dans certains cas, mais l’augmenter sans mesure déplace seulement la pression vers la mémoire.
  • Pour les uploads : Streamer directement vers un stockage objet ou une pipeline de traitement au lieu de bufferiser tout le fichier en mémoire.

Rareté : Moyen Difficulté : Difficile


6. Comment fonctionne le module cluster ?

Réponse : Étant donné que Node.js est monothread, il s'exécute sur un seul cœur de CPU. Le module cluster vous permet de créer des processus enfants (workers) qui partagent le même port de serveur.

  • Processus Maître : Gère les workers.
  • Processus Workers : Chacun exécute une instance de votre application.
  • Avantage : Vous permet d'utiliser tous les cœurs de CPU disponibles, ce qui augmente le débit.

Rareté : Courant Difficulté : Moyen


7. Worker Threads vs module Cluster : Quand utiliser lequel ?

Réponse :

  • Cluster : Crée des processus séparés. Chacun a son propre espace mémoire et son propre instance V8. Idéal pour la mise à l'échelle des serveurs HTTP (liés aux E/S).
  • Worker Threads : Crée des threads au sein d'un seul processus. Ils partagent la mémoire (via SharedArrayBuffer). Idéal pour les tâches gourmandes en CPU (par exemple, le traitement d'images, la cryptographie) afin d'éviter de bloquer la boucle d'événements principale.

Rareté : Moyen Difficulté : Difficile


8. Comment gérez-vous les exceptions non interceptées et les rejets de promesses non gérés ?

Réponse :

  • Exception Non Interceptée : Écoutez process.on('uncaughtException', cb). Il est généralement préférable de consigner l'erreur et de redémarrer le processus (en utilisant un gestionnaire de processus comme PM2) car l'état de l'application peut être corrompu.
  • Rejet Non Géré : Écoutez process.on('unhandledRejection', cb).
  • Bonne Pratique : Utilisez toujours les blocs try/catch et .catch() sur les promesses.

Rareté : Courant Difficulté : Facile


9. Quel est le rôle de package-lock.json ?

Réponse : Il décrit l'arborescence exacte qui a été générée, de sorte que les installations ultérieures puissent générer des arborescences identiques, quelles que soient les mises à jour intermédiaires des dépendances. Il garantit que votre projet fonctionne exactement de la même manière sur chaque machine (CI/CD, autres développeurs).

Rareté : Courant Difficulté : Facile


10. Expliquez le concept de Middleware dans Express.js.

Réponse : Les fonctions de middleware sont des fonctions qui ont accès à l'objet requête (req), à l'objet réponse (res) et à la fonction middleware suivante dans le cycle requête-réponse de l'application (next).

  • Tâches : Exécuter du code, modifier les objets req/res, terminer le cycle requête-réponse, appeler le middleware suivant.
  • Ordre : Ils s'exécutent séquentiellement dans l'ordre dans lequel ils sont définis.

Rareté : Courant Difficulté : Facile


Conception de Système & Architecture (10 Questions)

11. Comment concevriez-vous une application de chat en temps réel ?

Réponse :

  • Protocole : WebSockets (en utilisant socket.io ou ws) pour une communication bidirectionnelle.
  • Backend : Node.js est idéal en raison de sa nature événementielle qui permet de gérer de nombreuses connexions simultanées.
  • Mise à l'échelle :
    • Redis Pub/Sub : Si vous avez plusieurs instances de serveur, un utilisateur connecté au serveur A doit envoyer un message à un utilisateur sur le serveur B. Redis Pub/Sub agit comme un courtier de messages pour diffuser les messages sur tous les serveurs.
  • Base de données :
    • Messages : NoSQL (MongoDB/Cassandra) pour un débit d'écriture élevé.
    • Utilisateurs : Relationnelle (PostgreSQL) ou NoSQL.

Rareté : Très Courant Difficulté : Difficile


12. Microservices dans Node.js : Schémas de communication.

Réponse :

  • Synchrone : HTTP/REST ou gRPC. Bon pour les requêtes/réponses simples.
  • Asynchrone : Files d'attente de messages (RabbitMQ, Kafka, SQS). Bon pour découpler les services et gérer les pics de charge.
  • Piloté par les événements : Les services émettent des événements, d'autres écoutent.

Rareté : Courant Difficulté : Moyen


13. Comment gérez-vous les transactions distribuées (Saga Pattern) ?

Réponse : Dans les microservices, une transaction peut s'étendre sur plusieurs services. Il est difficile de garantir ACID.

  • Saga Pattern : Une séquence de transactions locales. Chaque transaction locale met à jour la base de données et publie un événement ou un message pour déclencher la transaction locale suivante dans la saga.
  • Compensation : Si une transaction locale échoue, la saga exécute une série de transactions de compensation qui annulent les modifications apportées par les transactions locales précédentes.

Rareté : Moyen Difficulté : Difficile


14. Expliquez le modèle Circuit Breaker.

Réponse : Il empêche une application d'essayer à plusieurs reprises d'exécuter une opération qui est susceptible d'échouer (par exemple, appeler un microservice en panne).

  • États :
    • Closed (Fermé) : Les requêtes passent.
    • Open (Ouvert) : Les requêtes échouent immédiatement (fast fail) sans appeler le service.
    • Half-Open (Semi-Ouvert) : Autorise un nombre limité de requêtes pour vérifier si le service a récupéré.

Rareté : Moyen Difficulté : Moyen


15. Comment sécurisez-vous une API Node.js ?

Réponse : Une réponse solide commence par le threat modeling, pas par une simple liste de packages. Pour une API Node.js, couvrez :

  • Authentification et autorisation : Valider l’identité, appliquer les droits au niveau objet et ne pas faire confiance aux IDs utilisateur ou tenant fournis par le client.
  • Validation des entrées : Valider type, format, plage, content type et taille de requête à la frontière avec Zod, Joi ou un équivalent.
  • Transport et en-têtes : Utiliser HTTPS, des cookies sécurisés si nécessaire, des allowlists CORS et des en-têtes via Helmet ou la plateforme.
  • Protection contre les abus : Rate limits, timeouts, limites de taille de body et reverse proxy contre les clients lents ou massifs.
  • Dépendances et secrets : Verrouiller les dépendances, surveiller les vulnérabilités, garder les secrets hors du code et faire tourner les identifiants compromis.
  • Observabilité : Logger les échecs utiles à la sécurité sans exposer de données sensibles.

Rareté : Courant Difficulté : Moyen


16. Qu'est-ce que Serverless et comment s'intègre-t-il avec Node.js ?

Réponse : Serverless (par exemple, AWS Lambda) vous permet d'exécuter du code sans provisionner ni gérer de serveurs.

  • Intégration Node.js : Node.js est excellent pour le serverless en raison de son temps de démarrage rapide (cold start) et de sa nature légère.
  • Cas d'utilisation : Points de terminaison d'API, traitement d'événements (téléchargements S3), tâches planifiées.

Rareté : Moyen Difficulté : Moyen


17. Expliquez GraphQL vs REST. Quand utiliser GraphQL ?

Réponse :

  • REST : Plusieurs points de terminaison, sur-extraction ou sous-extraction de données.
  • GraphQL : Point de terminaison unique, le client demande exactement ce dont il a besoin.
  • Utiliser GraphQL : Lorsque vous avez des exigences de données complexes, plusieurs clients (web, mobile) nécessitant différentes formes de données, ou pour réduire les allers-retours réseau.

Rareté : Courant Difficulté : Moyen


18. Comment implémentez-vous la mise en cache dans Node.js ?

Réponse :

  • En mémoire : node-cache (bon pour une seule instance, mais les données sont perdues au redémarrage et ne sont pas partagées).
  • Distribuée : Redis (norme industrielle).
  • Stratégies : Cache-Aside, Write-Through.
  • Mise en cache HTTP : Utilisez les en-têtes ETag, Cache-Control.

Rareté : Courant Difficulté : Moyen


19. Pool de connexions à la base de données.

Réponse : Ouvrir une nouvelle connexion à la base de données pour chaque requête est coûteux.

  • Pooling : Maintient un cache de connexions à la base de données qui peuvent être réutilisées.
  • Node.js : Les bibliothèques comme pg (PostgreSQL) ou mongoose gèrent automatiquement le pooling. Vous devez configurer la taille du pool en fonction de votre charge de travail et des limites de la base de données.

Rareté : Moyen Difficulté : Moyen


20. Comment gérez-vous les téléchargements de fichiers dans Node.js ?

Réponse :

  • Multipart/form-data : L'encodage standard pour les téléchargements de fichiers.
  • Bibliothèques : multer (middleware pour Express), formidable, busboy.
  • Stockage : Ne stockez pas les fichiers dans le système de fichiers du serveur (statelessness). Téléchargez vers un stockage cloud comme AWS S3. Diffusez le fichier directement vers S3 pour éviter de le charger en mémoire.

Rareté : Courant Difficulté : Moyen


Performance & Tests (10 Questions)

21. Comment déboguez-vous une fuite de mémoire dans Node.js ?

Réponse :

  • Symptômes : Augmentation de l'utilisation de la mémoire au fil du temps (RSS), plantage éventuel.
  • Outils :
    • Node.js Inspector : Flag --inspect, se connecter avec Chrome DevTools.
    • Heap Snapshots : Prenez des instantanés du tas et comparez-les pour trouver les objets qui ne sont pas collectés par le garbage collector.
    • process.memoryUsage() : Surveiller par programme.

Rareté : Courant Difficulté : Difficile


22. Profilage des applications Node.js.

Réponse : Le profilage permet d'identifier les goulots d'étranglement du CPU.

  • Profiler intégré : node --prof app.js. Génère un fichier journal. Traitez-le avec node --prof-process isolate-0x...log.
  • Clinic.js : Une suite d'outils (clinic doctor, clinic flame, clinic bubbleprof) pour diagnostiquer les problèmes de performance.

Rareté : Moyen Difficulté : Difficile


23. Expliquez la règle "Ne bloquez pas la boucle d'événements".

Réponse : Puisqu'il n'y a qu'un seul thread, si vous exécutez une opération synchrone de longue durée (par exemple, un calcul lourd, une lecture de fichier synchrone, une regex complexe), la boucle d'événements s'arrête. Aucune autre requête ne peut être traitée.

  • Solution : Partitionnez le calcul (setImmediate), utilisez des Worker Threads ou déchargez vers un microservice.

Rareté : Très Courant Difficulté : Facile


24. Tests unitaires vs tests d'intégration dans Node.js.

Réponse :

  • Tests unitaires : Tester des fonctions/modules individuels de manière isolée. Simuler les dépendances. (Outils : Jest, Mocha, Chai).
  • Tests d'intégration : Tester comment les modules fonctionnent ensemble (par exemple, point de terminaison d'API + base de données). (Outils : Supertest).

Rareté : Courant Difficulté : Facile


25. Qu'est-ce que TDD (Test Driven Development) ?

Réponse : Un processus de développement où vous écrivez le test avant le code.

  1. Écrivez un test qui échoue (Rouge).
  2. Écrivez le minimum de code pour réussir le test (Vert).
  3. Refactorisez le code (Refactor).

Rareté : Moyen Difficulté : Moyen


26. Comment gérez-vous la journalisation (logging) dans une application Node.js de production ?

Réponse : Le logging de production doit être structuré, consultable et sûr pour les outils d’observabilité.

  • Utiliser un logger : Pino, Winston ou le logger de la plateforme plutôt que des console.log dispersés.
  • Structure : Émettre du JSON avec request ID, identifiants utilisateur ou tenant si c’est sûr, route, statut, latence et métadonnées d’erreur.
  • Niveaux : Utiliser error, warn, info et debug de manière cohérente.
  • Masquage : Ne jamais logger de tokens, mots de passe, données de paiement complètes ou contenu privé utilisateur.
  • Corrélation : Relier logs, métriques et traces pour diagnostiquer les incidents entre services.

Rareté : Courant Difficulté : Facile


27. Expliquez le versionnage sémantique (SemVer).

Réponse : Format : MAJOR.MINOR.PATCH (par exemple, 1.2.3).

  • MAJOR : Changements d'API incompatibles.
  • MINOR : Fonctionnalité rétrocompatible.
  • PATCH : Corrections de bugs rétrocompatibles.
  • ^ vs ~ : ^1.2.3 met à jour vers <2.0.0. ~1.2.3 met à jour vers <1.3.0.

Rareté : Courant Difficulté : Facile


28. Que sont les variables d'environnement et comment les gérez-vous ?

Réponse :

  • Objectif : Configuration qui varie entre les environnements (Dev, Staging, Prod) comme les URL de la base de données, les clés API.
  • Utilisation : process.env.VARIABLE_NAME.
  • Gestion : Fichiers .env (en utilisant le package dotenv) pour le développement local. En production, définissez-les dans les paramètres du système d'exploitation ou du conteneur/plateforme.

Rareté : Courant Difficulté : Facile


29. Comment déployez-vous une application Node.js ?

Réponse :

  • Gestionnaire de processus : PM2 (maintient l'application en vie, gère les redémarrages, les journaux).
  • Proxy inverse : Nginx (gère SSL, les fichiers statiques, l'équilibrage de charge) -> Application Node.js.
  • Conteneurisation : Docker (standard).
  • Orchestration : Kubernetes.
  • CI/CD : GitHub Actions, Jenkins.

Rareté : Courant Difficulté : Moyen


30. Qu'est-ce qu'un Event Emitter ?

Réponse : Le module events est le cœur de l'architecture événementielle de Node.js.

  • Utilisation :
    const EventEmitter = require('events');
    const myEmitter = new EventEmitter();
    myEmitter.on('event', () => console.log('an event occurred!'));
    myEmitter.emit('event');
  • De nombreux modules principaux l'étendent : fs.ReadStream, net.Server, http.Server.

Rareté : Courant Difficulté : Facile

Newsletter subscription

Conseils de carrière hebdomadaires qui fonctionnent vraiment

Recevez les dernières idées directement dans votre boîte de réception

Votre Prochain Entretien n'est qu'à un CV

Créez un CV professionnel et optimisé en quelques minutes. Aucune compétence en design nécessaire—juste des résultats prouvés.

Créer mon CV

Partager cet article

Doublez Vos Rappels d'Entretien

Les candidats qui adaptent leur CV à la description du poste obtiennent 2,5 fois plus d'entretiens. Utilisez notre IA pour personnaliser automatiquement votre CV pour chaque candidature instantanément.