Développeur full stack Questions d'entretien & Réponses

Les entretiens de développeur full stack évaluent votre capacité à travailler sur l'ensemble de la pile applicative : de la conception de base de données à l'implémentation de l'interface utilisateur. Attendez-vous à des questions testant les connaissances frontend et backend, plus des décisions architecturales.

Questions comportementales

  1. 1. Décrivez une fonctionnalité que vous avez construite de bout en bout, de la base de données à l'interface utilisateur.

    Exemple de réponse

    J'ai développé un fil d'activité en temps réel pour un outil de gestion de projet. Côté backend, j'ai conçu un système d'event sourcing avec PostgreSQL : chaque action (tâche créée, commentaire ajouté, statut modifié) générait un enregistrement d'événement avec horodatage, acteur, type d'action et métadonnées. J'ai créé un endpoint d'API Node.js avec pagination par curseur et des canaux WebSocket pour les mises à jour en temps réel. Côté frontend, j'ai développé un composant React utilisant une liste virtualisée (react-window) pour gérer des fils avec plus de 10 000 événements sans problèmes de performance DOM. Les nouveaux événements apparaissaient en temps réel via WebSocket avec des animations d'insertion fluides. J'ai également ajouté des filtres par type d'événement et par personne, s'appuyant sur un index partiel PostgreSQL dédié. La fonctionnalité a été livrée en 5 semaines et est devenue la page la plus utilisée de l'application : 78 % des utilisateurs actifs quotidiens la visitaient au moins une fois par session.

  2. 2. Décrivez une situation où vous avez dû choisir entre le frontend et le backend pour implémenter une logique métier.

    Exemple de réponse

    Nous avions besoin de calculs de tarification pour un outil de devis. Le chef de projet voulait des mises à jour de prix instantanées lorsque les utilisateurs modifiaient les quantités et les options. L'implémentation initiale plaçait toute la logique de tarification dans le frontend React pour un retour immédiat. Ça fonctionnait jusqu'à ce que nous découvrions des incohérences : le frontend calculait 1 247 € mais l'API de confirmation de commande retournait 1 251 € en raison d'approches d'arrondi différentes. J'ai déplacé la logique de tarification canonique vers l'API backend et créé un estimateur frontend léger utilisant des règles simplifiées pour un retour instantané, clairement étiqueté « prix estimé ». Quand l'utilisateur finalisait le devis, le backend calculait le prix exact. Ce modèle « frontend optimiste, backend autoritaire » répondait aux deux exigences de rapidité et de précision. La leçon : les calculs critiques pour l'entreprise doivent avoir une source de vérité unique côté backend. Le frontend peut approximer pour l'expérience utilisateur, mais c'est le serveur qui décide.

  3. 3. Parlez d'une fois où vous avez amélioré le flux de travail de développement pour votre équipe.

    Exemple de réponse

    Notre équipe avait des dépôts frontend et backend séparés avec des cycles de déploiement différents. Les développeurs frontend attendaient constamment que les API backend soient prêtes avant de pouvoir intégrer. J'ai introduit deux changements. D'abord, j'ai mis en place un flux de développement API contract-first en utilisant des spécifications OpenAPI : nous nous accordions sur le contrat API avant que l'une ou l'autre partie ne commence à construire, puis les équipes frontend et backend développaient en parallèle en utilisant la spécification comme source de vérité. J'ai configuré des serveurs mock à partir de la spécification OpenAPI pour que le frontend puisse développer avec des réponses réalistes avant que le backend ne soit prêt. Ensuite, j'ai créé une configuration docker-compose permettant de lancer toute la pile localement avec une seule commande, y compris le seeding de la base de données et les services externes simulés. Les problèmes d'intégration qui apparaissaient auparavant en staging surgissaient désormais sur les machines des développeurs. Le résultat : le taux de complétion des sprints est passé de 68 % à 91 % car les dépendances inter-équipes ne bloquaient plus l'avancement.

  4. 4. Donnez-moi un exemple de la façon dont vous avez géré une migration de données complexe entre des systèmes.

    Exemple de réponse

    Nous avons migré les données utilisateurs de Firebase vers PostgreSQL tout en maintenant l'application React opérationnelle. Le défi : 200 000 utilisateurs avec des structures de documents imbriquées devant être normalisées en tables relationnelles. J'ai construit un pipeline de migration en trois phases. Phase 1 : conception du schéma. J'ai mappé les structures de documents Firebase vers des tables PostgreSQL, en normalisant les tableaux imbriqués en tables de jonction. Phase 2 : fonctionnement parallèle. L'application écrivait simultanément dans Firebase et PostgreSQL via une couche middleware. Les lectures restaient sur Firebase. Phase 3 : validation et bascule. J'ai écrit un script de réconciliation qui comparait 10 000 enregistrements aléatoires entre les deux bases de données chaque nuit. Après 2 semaines sans aucune divergence, nous avons basculé les lectures vers PostgreSQL et désactivé les écritures Firebase. Durée totale de la migration : 4 semaines sans aucune interruption de service côté utilisateur. Le script de réconciliation a détecté 3 cas limites dans la logique d'écriture duale qui auraient causé des pertes de données dans une migration big bang.

Questions techniques

  1. 1. Comment concevriez-vous un éditeur de documents collaboratif en temps réel ?

    Exemple de réponse

    Le défi central est la résolution des conflits : plusieurs utilisateurs éditent simultanément. J'utiliserais la Transformation Opérationnelle (OT) ou les CRDTs (types de données répliquées sans conflit). Les CRDTs sont plus modernes et ne nécessitent pas de serveur central pour la résolution des conflits, ce qui les rend plus résilients. Architecture : le frontend utilise un éditeur de texte riche (Tiptap/ProseMirror) avec une bibliothèque CRDT (Yjs) qui gère les modifications locales de façon optimiste. Les changements se propagent via WebSocket vers un serveur Node.js qui les diffuse à tous les clients connectés. Le serveur persiste également l'état du document dans PostgreSQL sous forme de CRDT sérialisé à chaque modification (avec debounce pour éviter des écritures excessives). Pour la présence : chaque client envoie sa position de curseur et sa sélection via le canal WebSocket, et les autres clients affichent des curseurs colorés. Pour le support hors ligne : Yjs gère la fusion quand un client se reconnecte, en appliquant ses modifications hors ligne contre l'état actuel du document. Considérations de scalabilité : utiliser Redis Pub/Sub pour diffuser les modifications sur plusieurs instances de serveur, partitionner les connexions WebSocket par identifiant de document et implémenter le chargement paresseux pour les documents très longs.

  2. 2. Expliquez le rendu côté serveur par rapport au rendu côté client. Quand choisiriez-vous l'un ou l'autre ?

    Exemple de réponse

    Rendu côté client (CSR) : le serveur envoie une coquille HTML minimale, le JavaScript se télécharge et effectue le rendu de la page dans le navigateur. Avantages : transitions de page fluides, charge serveur réduite, bien adapté aux tableaux de bord authentifiés. Inconvénients : chargement initial plus lent (page blanche jusqu'à l'exécution du JS), mauvais référencement (les moteurs de recherche n'exécutent pas forcément le JS), Core Web Vitals dégradés. Rendu côté serveur (SSR) : le serveur génère le HTML complet pour chaque requête. Avantages : premier affichage de contenu rapide, excellent référencement, fonctionne sans JavaScript. Inconvénients : charge serveur élevée, les rechargements complets de page semblent plus lents, plus difficile à implémenter pour les fonctionnalités interactives. Je choisis le CSR pour les applications authentifiées (tableaux de bord, panneaux d'administration, outils SaaS) où le référencement importe peu et l'interactivité est prioritaire. Je choisis le SSR pour le contenu public (sites marketing, blogs, pages produits e-commerce) où le référencement et le temps de chargement initial sont critiques. Les frameworks modernes (Next.js, Nuxt, Remix) permettent de combiner les deux : SSR pour le chargement initial avec hydratation côté client pour l'interactivité. La génération de site statique (SSG) est encore meilleure pour le contenu qui ne change pas à chaque requête.

  3. 3. Comment gérez-vous l'authentification dans une application full stack ?

    Exemple de réponse

    J'implémente une authentification par JWT avec une stratégie de jetons spécifique. Le jeton d'accès (JWT) est de courte durée (15 minutes), contient l'identité et les rôles de l'utilisateur, et est envoyé dans l'en-tête Authorization. Le jeton de rafraîchissement est de longue durée (7 jours), opaque (non JWT), stocké dans un cookie HTTP-only Secure SameSite, et mappé à un enregistrement en base de données pour pouvoir être révoqué. Le flux : l'utilisateur se connecte, le serveur valide les identifiants, retourne le jeton d'accès dans le corps de la réponse et définit le cookie de rafraîchissement. Le frontend stocke le jeton d'accès en mémoire (pas dans localStorage, vulnérable aux XSS). Quand le jeton d'accès expire, le frontend appelle silencieusement l'endpoint de rafraîchissement, qui valide le cookie et retourne un nouveau jeton d'accès. À la déconnexion, les deux jetons sont invalidés côté serveur. Pour OAuth (Google, GitHub), j'utilise le flux d'autorisation par code : redirection vers le fournisseur, réception du code sur le callback, échange du code contre les jetons du fournisseur côté serveur, création ou liaison du compte utilisateur, et émission de notre propre JWT. Je ne fais jamais confiance directement aux jetons côté client provenant des fournisseurs OAuth.

  4. 4. Quelle est votre approche de la gestion des erreurs sur l'ensemble de la pile ?

    Exemple de réponse

    J'implémente la gestion des erreurs à quatre niveaux. API backend : toutes les erreurs retournent un format JSON cohérent avec un code de statut, un code d'erreur (lisible par la machine), un message (lisible par l'humain) et un champ de détails optionnel. J'utilise correctement les codes de statut HTTP : 400 pour la validation, 401 pour l'authentification, 403 pour les autorisations, 404 pour les ressources introuvables, 409 pour les conflits, 500 pour les erreurs serveur. Je n'expose jamais les traces de pile ni les détails internes dans les réponses en production. Couche service backend : try/catch autour des appels externes et des opérations de base de données, avec des types d'erreurs spécifiques (NotFoundError, ValidationError, ConflictError) qui correspondent aux réponses HTTP. Les erreurs non gérées passent par un gestionnaire d'erreurs global qui journalise l'erreur complète et retourne un 500 générique. Couche API frontend : un client API centralisé qui gère les erreurs courantes : 401 déclenche le rafraîchissement du jeton, 403 affiche un refus d'accès, 429 affiche un message de limite de débit, 500 affiche une erreur générique avec option de réessai. Interface utilisateur frontend : des error boundaries interceptent les erreurs de rendu, des notifications toast pour les erreurs non bloquantes, et de la validation en ligne pour les erreurs de formulaire. Chaque erreur est journalisée : les erreurs serveur dans les journaux structurés (Pino), les erreurs client dans un service de suivi des erreurs (Sentry).

Questions situationnelles

  1. 1. Vous développez une nouvelle fonctionnalité et devez décider entre une architecture monolithique ou microservices. Comment prenez-vous cette décision ?

    Exemple de réponse

    Je commencerais par un monolithe, sauf raison impérative de faire autrement. Les microservices ajoutent une complexité opérationnelle (réseau, déploiement, monitoring, débogage de systèmes distribués) qui n'est justifiée qu'à certaines tailles d'équipe et exigences d'échelle. Je choisirais un monolithe quand : l'équipe compte moins de 10 ingénieurs, le produit n'a pas encore atteint l'adéquation produit-marché (l'itération rapide prime sur la scalabilité), et il n'y a pas de besoin immédiat de mise à l'échelle ou de déploiement indépendants de composants spécifiques. Je choisirais des microservices quand : différents composants ont des besoins de mise à l'échelle très différents (un processeur d'images gourmand en CPU face à une API légère), les équipes doivent déployer indépendamment (10 ingénieurs ou plus, plusieurs squads), ou le domaine se décompose naturellement en contextes délimités distincts. Le juste milieu pragmatique : construire un monolithe modulaire avec des frontières internes claires. Si un module doit devenir un service ultérieurement, la séparation est nette. Cela évite la complexité des systèmes distribués tout en conservant la possibilité de séparer quand le besoin est réel.

  2. 2. Le designer veut une animation complexe qui fonctionne sur mobile, mais vous avez des inquiétudes concernant les performances. Comment gérez-vous cela ?

    Exemple de réponse

    Je commencerais par un prototype plutôt que de spéculer. Je construirais l'animation en utilisant des transformations CSS et l'opacité (qui sont accélérées par le GPU et ne déclenchent pas de recalcul de mise en page) et je testerais sur un appareil Android milieu de gamme représentatif, pas sur mon MacBook Pro. Si ça tourne à 60 fps sur cet appareil, on livre. Sinon, je diagnostiquerais le goulot d'étranglement avec le panneau de performance des Chrome DevTools : est-ce du layout thrashing, des opérations de peinture ou un blocage du thread principal ? Ensuite, je proposerais des alternatives selon le problème spécifique. Peut-être utiliser l'API Web Animations pour un meilleur ordonnancement des images. Peut-être réduire le nombre d'éléments animés. Peut-être utiliser will-change pour promouvoir les couches vers le GPU. Peut-être que l'animation se joue une seule fois au lieu de se répéter en boucle. Je présenterais au designer un spectre : « Voici l'animation complète à 30 fps sur mobile. Voici une version simplifiée à 60 fps. Voici une alternative statique. » Laissons-les choisir le compromis. Souvent, les designers préfèrent la version simple et fluide à la version complexe et saccadée.

  3. 3. Vous remarquez que le frontend effectue 15 appels API au chargement de la page. Comment optimisez-vous cela ?

    Exemple de réponse

    Je commencerais par comprendre pourquoi : ces appels sont-ils indépendants ou ont-ils des dépendances ? Sont-ils tous nécessaires pour le rendu initial ? Mes stratégies d'optimisation par ordre d'impact : d'abord, identifier les appels non nécessaires pour le rendu initial et les différer : charger les données sous le pli au défilement, charger les panneaux secondaires à l'interaction. Cela pourrait réduire les appels initiaux de 15 à 5. Ensuite, regrouper les appels liés : si nous récupérons séparément le profil utilisateur, les paramètres utilisateur et les notifications utilisateur, créer un endpoint BFF (Backend for Frontend) qui retourne toutes les données utilisateur en un seul appel. Troisièmement, utiliser GraphQL ou un modèle d'API composite si la fragmentation est un problème systémique : laisser le frontend demander exactement les données dont il a besoin en un seul appel. Quatrièmement, mettre en cache agressivement : utiliser le modèle stale-while-revalidate de React Query pour les données qui ne changent pas souvent. Cinquièmement, précharger : si l'utilisateur est susceptible de naviguer vers la page B depuis la page A, commencer à récupérer les données de la page B au survol. Je mesurerais l'impact : temps de chargement total de la page, Time to Interactive et nombre de requêtes réseau.

  4. 4. Un client demande une fonctionnalité qui lui conviendrait mais qui introduirait de la dette technique pour la plateforme. Comment gérez-vous cela ?

    Exemple de réponse

    Je quantifierais la dette plutôt que de simplement l'étiqueter « dette technique ». Qu'est-ce qui va concrètement casser ou devenir plus difficile ? Combien de fonctionnalités futures sont affectées ? Quel est le coût de maintenance sur 12 mois ? Ensuite, je proposerais des alternatives. Option A : construire de la « bonne » façon, ce qui prend plus de temps mais n'ajoute aucune dette. Option B : construire la version du client derrière un feature flag comme extension personnalisée, avec un plan pour la généraliser quand d'autres clients auront besoin de fonctionnalités similaires. Option C : construire la version rapide avec un élément de dette documenté, un calendrier de refactoring validé et l'acceptation du product owner que cela crée un coût de maintenance. Je présenterais le compromis clairement : « Nous pouvons livrer en 2 semaines avec l'approche C, mais cela ralentira la Fonctionnalité X au prochain trimestre d'une semaine et la Fonctionnalité Y de 3 jours. » En général, quand on quantifie le coût en aval, la décision devient évidente. Si l'entreprise décide que la rapidité vaut la dette, c'est une décision légitime, mais elle doit être explicite.

Conseils pour l'entretien

N'essayez pas d'être également profond dans tout : ayez un côté fort (frontend ou backend) et démontrez une compétence solide de l'autre. Préparez-vous à écrire du code dans un framework frontend et un langage backend pendant l'entretien.

Entraînez-vous avec l'IA

Essayez un entretien simulé gratuit

Entraînez-vous avec l'IA

Questions fréquentes

Comment se préparer à un entretien full stack ?
Couvrez les deux côtés : frontend (React/Vue, HTML/CSS, gestion d'état) et backend (conception API, modélisation de base de données, authentification). Préparez aussi la conception système full stack.
Les entretiens full stack favorisent-ils le frontend ou le backend ?
Cela dépend de l'entreprise. Les startups veulent souvent des compétences équilibrées. Les grandes entreprises peuvent avoir des rôles penchés vers un côté.
Les connaissances DevOps sont-elles importantes ?
De plus en plus. Les développeurs full stack doivent déployer leur propre code, configurer des pipelines CI/CD et dépanner les problèmes de production.
Dois-je construire un projet portfolio ?
Un projet full stack bien construit est une preuve convaincante de vos capacités. Choisissez quelque chose avec authentification, base de données, interface responsive et déploiement.

Postes similaires

Articles connexes

Nous utilisons des cookies pour analyser le trafic et améliorer votre expérience. Vous pouvez modifier vos préférences à tout moment. Cookie Policy