Le poste consiste à écrire des API et des services de traitement avec une pile purement fonctionnelle. Côté Typelevel, on trouve Cats et Cats Effect, http4s pour le HTTP, Doobie ou Skunk pour PostgreSQL, fs2 pour les flux et Circe pour le JSON. Côté ZIO, ZIO 2 avec ses ZLayer, zio-http, zio-json et Quill. Les deux écosystèmes répondent aux mêmes besoins, et une équipe en choisit un. Scala 3 se répand, avec given, extensions et enums.
La difficulté vient des profils qui connaissent les mots sans le modèle. Beaucoup de développeurs Scala ont surtout écrit du Spark, ou du Play avec des Future. Ils parlent de monades, mais confondent description et exécution, appellent unsafeRunSync au milieu du code, oublient de libérer une ressource ou bloquent le pool de calcul avec un appel JDBC. Demandez la différence entre un Future et un IO, ou ce que devient une connexion quand sa fibre est annulée.
Cats Effect 2 et ZIO 1 ont été remplacés depuis plusieurs années, et un profil qui n'a connu qu'eux devra se mettre à jour. Scala 3.9 est la nouvelle version LTS depuis septembre 2026, et les notes de version de ZIO 2.1.27 prévoient de l'exiger pour la suite. Le PDF comprend un cas de 20 minutes sur un service d'import de fichiers.
Cats Effect, ZIO et les bibliothèques autour
Cats
La bibliothèque des typeclasses du Scala fonctionnel : Functor, Applicative, Monad, Traverse, Semigroup. Elle apporte aussi des types pratiques comme NonEmptyList ou Validated, qui cumule les erreurs de validation. Un candidat doit savoir quand traverse remplace une boucle.
Cats Effect 3
Le runtime d'effets de Typelevel. IO décrit un programme sans l'exécuter, les fibres sont des tâches légères et annulables, Resource garantit la fermeture d'une connexion ou d'un fichier, Ref et Deferred gèrent l'état partagé. Le runtime sépare le pool de calcul des appels bloquants, qu'on signale avec IO.blocking.
ZIO 2
L'autre écosystème, développé à part de Typelevel. Le type ZIO[R, E, A] porte l'environnement, l'erreur typée et le résultat. Les ZLayer construisent les dépendances au démarrage, et les erreurs métier se séparent des pannes inattendues. Une équipe ZIO utilise souvent zio-http, zio-json et ZIO Test.
http4s
Le serveur et client HTTP de Typelevel, construit sur Cats Effect et fs2. Une route est une fonction de la requête vers la réponse, et les middlewares se composent autour. La série stable est la 0.23, la 1.0 est encore en versions milestone.
Doobie et Skunk
Doobie enveloppe JDBC dans un style fonctionnel : requêtes typées, transactions décrites comme des valeurs, Transactor qui gère le pool. Skunk parle directement le protocole PostgreSQL, sans JDBC. Avec Doobie, les appels JDBC restent bloquants et tournent sur un pool à part.
fs2 et ZStream
Les bibliothèques de flux. Elles traitent un fichier, un topic Kafka (fs2-kafka, zio-kafka) ou une socket élément par élément, avec une mémoire constante et des ressources libérées même en cas d'erreur. C'est l'outil des traitements volumineux, là où une collection chargée en entier ferait tomber la JVM.
Tagless final
Un style où les services sont des traits paramétrés par un type d'effet F[_], avec des contraintes comme Async ou Concurrent. Il facilite les tests et le changement d'effet, au prix de signatures plus lourdes. Certaines équipes s'en passent et écrivent directement en IO ou en ZIO, et un bon profil sait défendre l'une ou l'autre position.
Scala 3 et sbt
Scala 3 remplace les implicits par given et using, et ajoute les enums, les extensions et les types opaques. sbt reste l'outil de build le plus répandu, Mill et scala-cli existent aussi. La migration depuis Scala 2.13 se fait module par module, et les macros sont à réécrire.
Les équipes qui travaillent en Scala fonctionnel ont fait un choix explicite d'architecture, et l'entretien doit vérifier que la personne le partage en pratique. Sur une base de code existante, le développeur suit les conventions en place : tagless final ou IO concret, Either ou exceptions pour les erreurs, Cats Effect ou ZIO. Sur un nouveau service, il pèse ces choix et sait expliquer leur coût aux autres développeurs. Les offres françaises qui citent Cats ou ZIO sont rares, et beaucoup d'annonces Scala visent en réalité la data avec Spark. Écrivez la pile dans l'annonce pour éviter les malentendus.
Points de vérification pour un profil Cats Effect ou ZIO
- Effets et évaluation différée (IO, ZIO)
- Typeclasses et abstractions Cats
- Concurrence par fibres et annulation
- Gestion des ressources et des erreurs
- HTTP et accès aux données (http4s, Doobie, zio-http)
- Scala 3 et modélisation par les types
Questions sur les effets, les fibres et les ressources
Chaque question vient avec ce qu'une bonne réponse contient et le signal qui doit vous alerter. Pas besoin d'être technique pour les poser : écoutez si le candidat raconte du vécu.
Question 1 · junior à confirmé
Quelle différence voyez-vous entre un Future et un IO de Cats Effect ?
Une bonne réponseUn Future démarre dès sa création et garde son résultat en mémoire : le créer, c'est lancer le calcul. Un IO décrit un programme qui ne s'exécute qu'au moment où le runtime le lance, et qu'on peut relancer, combiner ou annuler. On peut remplacer un IO par sa définition sans changer le comportement du programme (transparence référentielle), ce qui est faux pour un Future. Un IO s'annule, un Future non.
Signal d'alerte« C'est la même chose avec une autre syntaxe », ou ne pas voir qu'un val f = Future(...) lance déjà l'appel.
Question 2 · confirmé
Votre service ouvre un pool de connexions, un client HTTP et un consommateur Kafka au démarrage. Comment garantissez-vous qu'ils sont fermés, même en cas d'erreur ou d'arrêt ?
Une bonne réponseChaque élément est un Resource, ou une ZLayer scoped côté ZIO, qui décrit son ouverture et sa fermeture. On les compose dans un for, et l'ensemble est utilisé dans un IOApp. À l'arrêt, sur une erreur ou une annulation, les ressources sont libérées dans l'ordre inverse de leur ouverture. Pas de close() manuel dans un finally autour d'un code d'effet.
Signal d'alerteUn try/finally autour d'un unsafeRunSync, ou rien de prévu pour l'annulation.
Question 3 · confirmé
Un appel JDBC tourne dans un IO, et le service répond de plus en plus lentement sous charge. Pourquoi ?
Une bonne réponseLe pool de calcul de Cats Effect compte autant de threads que de cœurs. Un appel bloquant y immobilise un thread, et quelques appels simultanés suffisent à arrêter toutes les autres fibres. L'appel doit être déclaré avec IO.blocking ou IO.interruptible, qui le déplacent sur un pool prévu pour bloquer. Doobie isole déjà ses appels JDBC, et côté ZIO on utilise ZIO.attemptBlocking.
Signal d'alerteAgrandir le pool de calcul, ou passer par un Future sur l'ExecutionContext global.
Question 4 · senior
Écrivez la signature d'un dépôt d'utilisateurs en style tagless final. Qu'est-ce que ce style vous apporte, et qu'est-ce qu'il coûte ?
Une bonne réponsetrait UserRepo[F[_]] { def find(id: UserId): F[Option[User]] }, avec une implémentation en IO pour la production et une autre en mémoire, sur un Ref, pour les tests. Chaque fonction demande la capacité minimale, Monad ou Concurrent quand il faut un Ref. Le coût : des signatures plus lourdes, des contraintes qui se propagent, des erreurs de compilation difficiles, et une abstraction inutile si l'équipe n'utilisera jamais autre chose qu'IO. Un bon profil défend un choix clair.
Signal d'alerteRéciter la définition sans pouvoir dire quand s'en passer, ou des contraintes Async partout par défaut.
Question 5 · junior à confirmé
Vous validez un formulaire de dix champs. Comment renvoyez-vous toutes les erreurs d'un coup au lieu de la première seulement ?
Une bonne réponseEither s'arrête à la première erreur, car sa composition est séquentielle. ValidatedNel cumule les erreurs grâce à son instance Applicative : on valide chaque champ, puis on combine avec mapN. EitherNel avec parMapN donne le même résultat. Côté ZIO, ZIO.validate ou la Validation de zio-prelude.
Signal d'alerteUne suite de if qui remplit une liste mutable d'erreurs, ou un flatMap sur Validated.
Recevez la fiche d'entretien complète en PDF
La fiche pour mener l'entretien de bout en bout, prête à imprimer ou à partager avec le manager.
- 30 questions sur 6 axes, avec la bonne réponse, le signal d'alerte et la relance
- Le niveau visé pour chaque question
- Une mise en situation de 20 minutes et ce qu'on attend du candidat
- La grille d'évaluation de 1 à 4, axe par axe
Cats, ZIO, Spark, Scala 3 : réponses pour le recrutement
Cats Effect ou ZIO : un profil formé sur l'un s'adapte-t-il à l'autre ?
Oui, dans la plupart des cas. Exigez la bibliothèque de l'équipe seulement si la personne doit être autonome dès les premiers jours. Les deux reposent sur les mêmes idées : des effets décrits comme des valeurs, des fibres, des ressources. Un bon développeur passe de l'un à l'autre sans repartir de zéro. Les écarts portent sur les erreurs typées, l'injection des dépendances (ZLayer d'un côté, paramètres ou tagless final de l'autre) et les bibliothèques autour. Vérifiez d'abord le modèle.
Un développeur Scala Spark peut-il tenir un poste Scala fonctionnel ?
Il connaît le langage, les case classes et les collections, mais Spark n'utilise presque pas les effets, les fibres ni les typeclasses de Cats. Le passage demande un vrai apprentissage. En entretien, posez les questions sur Future et IO, sur Resource et sur la concurrence. Un profil Spark qui y répond bien a déjà pratiqué ce style ailleurs. Sinon, sa place est plutôt sur un poste de data engineer Scala.
Scala 2.13 ou Scala 3 : que vérifier sur le CV ?
Demandez sur quelle version la personne a travaillé et si elle a déjà migré un module. Scala 3 change la syntaxe des implicits avec given et using, réécrit le système de macros et modifie certaines règles de typage. Un code de production peut tourner sur l'une ou l'autre version. Scala 3.9 est devenue version LTS en septembre 2026, à côté de la 3.3, et ZIO prévoit de s'aligner dessus.
Que donner à coder pendant le test technique ?
Un test technique court, sous forme de petit service à compléter, en Cats Effect ou en ZIO selon l'équipe : une route HTTP, un dépôt en mémoire sur un Ref, un appel externe à protéger par un timeout et des relances. Une heure suffit pour voir comment la personne compose les effets, traite les erreurs et écrit ses tests. Pour un senior, ajoutez la revue d'un service qui ferme mal ses ressources ou bloque le pool de calcul.
Pour structurer vos autres entretiens, consultez aussi nos pages sur les questions d'entretien de recrutement, la méthode de l'entretien structuré et la grille d'évaluation d'entretien.




