Comment Doctolib compte rendre son monolithe modulaire
Conscient des limites de son architecture monolithique fortement sollicitée aux pics de la crise sanitaire, le spécialiste de la prise de rendez-vous médicaux commence tout juste à la rendre modulaire. Ses architectes IT prônent une « évolution en douceur ».
En 2018, Doctolib a administré la prise de 133 millions de rendez-vous médicaux. En 2019, depuis 2013, il en enregistrait 238 millions. C’était avant la pandémie de COVID-19. Sur le seul mois de décembre 2021, l’entreprise en a compté 60 millions. D’autant que la plateforme a permis d’organiser 14 millions de téléconsultations au cours de la crise sanitaire.
De quoi sérieusement mettre à mal l’architecture IT de la licorne. « Les rapports ont complètement changé », constate Nicolas Martignole, Principal Engineer chez Doctolib.
Sans compter le fait que la division produits et technologies de l’entreprise est passée de 120 employés en 2019, à 500 réparties dans trois pays en 2022, dont 283 développeurs situés à Nantes, Lyon, Berlin et Paris.
Lors de la conférence Duck d’OCTO technology à la fin du mois de mars 2022, deux ingénieurs de Doctolib ont évoqué les défis posés par cette rapide montée en charge. « En 2019, la philosophie de Doctolib était de toujours de prévoir un mur devant nous, et d’attendre le dernier moment pour changer [l’architecture] et la remettre en question », raconte Nicolas Martignole. L’ingénieur logiciel. « Cela passe par des processus qualité et de tests, un ensemble de méthodes qui, mises bout à bout, nous ont permis d’absorber la croissance ».
En clair, la croissance était escomptée. Habituellement, les équipes observaient une augmentation de 20 % du trafic Web tous les deux à trois mois. Cela n’a pas empêché l’émergence de défi de taille pour les membres de l’IT. Chaque année, la taille de l’architecture est multipliée par deux. « La croissance était déjà là, la vaccination et les tests ont ajouté des pics de charge », affirme David Gageot, Chief Architect chez Doctolib. Un défi supplémentaire cristallisé par un épisode particulièrement mémorable pour les équipes.
L’électrochoc du pass vaccinal
« Le 12 juillet 2021, quand le président de la République a annoncé la mise en place du pass vaccinal, chez Doctolib, nous n’étions pas du tout prêts », lance Nicolas Martignole. « Comme tout le monde, nous avons appris la nouvelle à la télévision. La plupart de nos collaborateurs étaient en vacances. Pendant plus de 2 h 30, nous sommes montés à plus de 10 millions de transactions Web par seconde sur la plateforme », ajoute-t-il. Cela représente 926 000 rendez-vous dans ce court laps de temps. Le 14 juillet, Doctolib en enregistrait 1,4 million.
Les équipes ont « activé tous les systèmes ». « Nous avons subi de la contention à l’entrée. Nous avons mis en place une salle d’attente », explique Nicolas Martignole. « Une fois que les utilisateurs accédaient à la plateforme, notre but était qu’ils sortent le plus rapidement possible une fois le rendez-vous pris ».
Les ingénieurs disent avoir « beaucoup appris » de cet épisode jalonné d’imprévus. « Nous nous sommes rendu compte que le mur pouvait nous tomber dessus », remarque Nicolas Martignole.
Ces imprévus sont liés aux comportements des utilisateurs. « Ce soir du 12 juillet, nous avons compris que les gens passaient beaucoup de temps à inscrire leurs enfants, chose que l’on n’avait pas anticipée », constate le principal engineer.
« La partition de musique était bonne », mais quelques fausses notes pouvaient se glisser en fonction des événements difficilement maîtrisables.
Ce n’est pas la première fois que Doctolib adapte son architecture aux aléas extérieurs et aux exigences des utilisateurs. Sur la même période, des mécanismes ont été petit à petit mis en place, en fonction des besoins exprimés ou observés des différents publics qui utilisent la plateforme Doctolib : les patients, les médecins et les hôpitaux, principalement.
Les équipes techniques qui misaient jusqu’alors sur une architecture ennuyeuse ont dû revoir quelque peu leurs approches. « Chez Doctolib, nous aimons le chiffre 1 : nous essayons de tout avoir en un seul exemplaire », indique David Gageot. Ainsi, les équipes IT s’appuient sur une unité de déploiement pour le site patient et pour le « back-end » des praticiens. Un seul runtime est lié à un seul backend développé avec le framework Ruby On Rails, tandis que le frontend est écrit en JavaScript et TypeScript. Une seule application mobile bâtie avec Electron sert de « wrapper » à la page du site Web Doctolib. Quant aux tests d’intégration continue, ils sont réalisés depuis une seule plateforme. Enfin, un seul dépôt Git propulse « le cœur du logiciel ».
En réalité, ce monolithe est au centre d’une « constellation » de fonctions et d’outils complémentaires. Une réalité qui n’est pas forcément toujours aux goûts des ingénieurs. « Les techs de Doctolib essayent de tordre le cou à la complexité », lance David Gageot. « Cette complexité qui émerge toute seule, nous essayons de ne pas la subir ».
« Nous avons tout de même conservé une forme de pragmatisme dans la gestion de l’architecture », rappelle le Chief Architect. Le monolithe en question couvre la France, l’Allemagne et l’Italie. « Cette vision monolithique nous convient toujours en 2022 ».
Car cette architecture monolithique n’empêche pas Doctolib d’adopter les services cloud modernes. Les équipes ont peuvent disposer jusqu’à 1 000 pods Kubernetes autoscalés sur AWS en lieu et place de machines virtuelles. Les ingénieurs déploient le CDN, le service de répartition de charges et le WAF de Cloudfare entre le front end et les Web apps.
Une base de données qui a beaucoup évolué
Mais selon les intervenants, « ce qui a le plus changé c’est la base de données ». D’un PostgreSQL standard, Doctolib a migré vers Aurora Serverless. Compatible avec le SGBD SQL, ce service doit permettre de bénéficier d’une mise à l’échelle automatique en fonction de l’utilisation et du volume de données stockées.
Ici, les ingénieurs jouent sur une configuration combinant un seul writer et plusieurs réplicas de lecture. Cette technique supportée nativement par PostgreSQL permet d’éviter la concurrence entre l’écriture et la lecture des données sur une ou plusieurs tables. Au plus gros de la crise, les équipes de Doctolib ont déployé jusqu’à treize services de lecture. La base de données en question contient 23 To de données et supporte jusqu’à 20 millions de requêtes par minute.
Selon les tests de charge effectués par les ingénieurs, cette architecture peut supporter le double de ce trafic et de ce volume, mais cela ne prend pas en compte les pics de charge liés aux événements particuliers comme la vaccination. « Nous n’allons pas forcément dimensionner la plateforme pour des pics qui ont lieu quelques fois par an. Cela reste du domaine de l’improbable, et cela coûte cher », remarque David Gageot.
Il y a tout de même un nouveau mur que les ingénieurs doivent anticiper. « Notre base de données commence à être à l’étroit. Nous sommes au maximum de ce que pouvons avoir sur un SGBD PostgreSQL », affirme le Chief Architect. Plusieurs options s’ouvrent à Doctolib. Certaines d’entre elles intiment de passer d’Aurora à une autre comme Citus, Yugabyte, ou Spanner. Ces SGBD semblent plus « élastiques » aux yeux des experts de l’entreprise. Une autre possibilité serait de déployer une deuxième base de données PostgreSQL. Deux SGBD provoqueraient « une révolution » qui mettrait à mal la philosophie de l’exemplaire unique décrite plus haut. Quelle que soit la décision future, il faudra conserver la « simplicité du build et du run ».
Un monolithe modulaire pour soulager les développeurs
Il n’est donc pas question d’employer une base de données par fonction applicative. En revanche, les ingénieurs favorisent l’adoption d’un « monolithe modulaire » qui embrasse réellement la notion de constellations dans son architecture sans la subir. Par exemple, pour pouvoir s’interfacer avec les services des hôpitaux, Doctolib déploie quelques services en Java, tandis que d’autres fonctions peuvent être écrites en Go. « C’est simple, mais pas simpliste », précise Davig Gageot.
Outre les limites techniques, les équipes commencent à sentir le poids de la charge cognitive, tant le volume de code, sa complexité et les efforts de maintien de la cohérence au sein du monolithe sont importants.
D’autant que les équipes de développement sont divisées en « feature teams » : chacune d’entre elles est responsable du développement et du maintien du code d’une fonction applicative. Aussi, les développeurs effectuent trois mises en production par jour.
« Avec le monolithe modulaire vient l’idée de conserver une seule unité de déploiement, une seule base de code, mais d’identifier plus clairement les différents modules fonctionnels et les différentes responsabilités », indique le Chief Architect.
Ce projet en cours d’élaboration depuis un an prend forme. « Nos moteurs Rails nous permettent de prendre des tranches d’applications et de le pousser tous ensemble en production », ajoute-t-il.
Doctolib a déjà des tranches applicatives pour les services au médecin, pour les exports de données, ou encore pour la téléconsultation.
« Cela rend le monolithe plus agréable à utiliser au quotidien pour les développeurs », assure David Gageot. « Nous n’avons pas de microservices, de ruptures de protocoles entre les composants, il nous suffit d’appeler une fonction Ruby ».
En cela, les « techs » s’inspirent du retour d’expérience de Shopify. Mais le véritable mur pour Doctolib sera d’adapter son système maison d’intégration continue.
« Nous avons une vision de la CI très particulière qui ne s’adapte pas aux outils du marché. Nous “mergeons” entre 50 et 100 pull requests par jour. Sur chaque Pull Request, nous lançons 40 000 tests, dont un tiers de tests bout en bout », raconte le Chief Architect.
Ce système de tests repose sur 12 clusters Kubernetes, dont certains intègrent 500 machines. Chaque cluster peut réaliser jusqu’à 5 000 tests en parallèle. « Nous commençons à atteindre les limites de cette chaîne “custom” », note David Gageot.
En aucun cas, il ne s’agit de « tout revoir ». De manière générale, les ingénieurs estiment que l’architecture s’est montrée résistante à la plupart des chocs. Il faudra tout de même prévoir d’autres « évolutions en douceur » pour éviter les prochains murs.