[{"data":1,"prerenderedAt":2466},["ShallowReactive",2],{"search-api":-1,"listing-tag-Architecture Distribuée-page-1":3},[4,816],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"id":11,"date":12,"listed":13,"nocomments":7,"hidden":7,"categories":14,"tags":15,"--cover":20,"readingTime":21,"body":26,"_type":810,"_id":811,"_source":812,"_file":813,"_stem":814,"_extension":815},"/fr/architecture-craft/database-per-service-microservices","architecture-craft",false,"","Database per Service : quand ça vaut vraiment la complexité","Le pattern Database per Service est présenté comme obligatoire en microservices. Il ne l'est pas. Le critère objectif pour décider — et les alternatives ignorées.",35,"2026-03-25",true,[6],[16,17,18,19],"Microservices","Database per Service","Architecture Distribuée","Base de Données","covers/articles/database-per-service-microservices.jpg",{"text":22,"minutes":23,"time":24,"words":25},"8 min read",7.61,456600,1522,{"type":27,"children":28,"toc":801},"root",[29,37,51,56,61,66,70,77,82,87,106,116,126,136,150,153,159,169,179,184,193,206,224,237,240,246,251,392,402,405,411,416,424,429,571,576,584,589,597,602,605,611,619,644,654,662,665,671,676,681,704,707,713,728,741,754,767,780,783,795],{"type":30,"tag":31,"props":32,"children":34},"element","h1",{"id":33},"database-per-service-quand-ça-vaut-vraiment-la-complexité",[35],{"type":36,"value":9},"text",{"type":30,"tag":38,"props":39,"children":40},"p",{},[41,43,49],{"type":36,"value":42},"J'ai accompagné un client dans le secteur du commerce en ligne qui avait adopté Database per Service dès le début, par principe, avant même d'avoir 5 développeurs. 18 mois plus tard, l'équipe de 6 développeurs backend passait ",{"type":30,"tag":44,"props":45,"children":46},"strong",{},[47],{"type":36,"value":48},"30% de son temps",{"type":36,"value":50}," à gérer l'infrastructure de 20 bases de données, les sagas qui échouaient partiellement, et les incohérences de données entre services.",{"type":30,"tag":38,"props":52,"children":53},{},[54],{"type":36,"value":55},"La décision que nous avons prise ensemble : migrer 15 des 20 services vers un schéma-per-service dans une base partagée. Seuls les 5 services critiques (ceux qui avaient vraiment des besoins différents de performance, d'isolation, ou de moteur) ont conservé leur base dédiée.",{"type":30,"tag":38,"props":57,"children":58},{},[59],{"type":36,"value":60},"Résultat : le temps passé à l'infrastructure est passé de 30% à 8%. L'équipe a pu réinvestir ces heures dans de la valeur produit.",{"type":30,"tag":38,"props":62,"children":63},{},[64],{"type":36,"value":65},"Database per Service n'est pas un impératif des microservices. C'est un trade-off. Et comme tout trade-off, il se décide selon le contexte, pas selon un dogme.",{"type":30,"tag":67,"props":68,"children":69},"hr",{},[],{"type":30,"tag":71,"props":72,"children":74},"h2",{"id":73},"le-problème-réel-que-database-per-service-résout",[75],{"type":36,"value":76},"Le problème réel que Database per Service résout",{"type":30,"tag":38,"props":78,"children":79},{},[80],{"type":36,"value":81},"Sam Newman dans \"Building Microservices\" (2014) a popularisé l'idée que chaque microservice devrait posséder ses données. L'intention était valide : éviter le couplage de base de données partagée qui crée des dépendances implicites entre services.",{"type":30,"tag":38,"props":83,"children":84},{},[85],{"type":36,"value":86},"Ces couplages sont réels :",{"type":30,"tag":38,"props":88,"children":89},{},[90,95,97,104],{"type":30,"tag":44,"props":91,"children":92},{},[93],{"type":36,"value":94},"Couplage de schéma :",{"type":36,"value":96}," si le service A modifie la table ",{"type":30,"tag":98,"props":99,"children":101},"code",{"className":100},[],[102],{"type":36,"value":103},"orders",{"type":36,"value":105},", le service B qui lit cette table peut casser sans que l'équipe A s'en rende compte.",{"type":30,"tag":38,"props":107,"children":108},{},[109,114],{"type":30,"tag":44,"props":110,"children":111},{},[112],{"type":36,"value":113},"Couplage de déploiement :",{"type":36,"value":115}," une migration de base de données doit être coordonnée avec tous les services qui lisent ou écrivent les tables concernées.",{"type":30,"tag":38,"props":117,"children":118},{},[119,124],{"type":30,"tag":44,"props":120,"children":121},{},[122],{"type":36,"value":123},"Couplage de performance :",{"type":36,"value":125}," une requête lente du service A consomme des ressources de connexion qui dégradent les performances du service B.",{"type":30,"tag":38,"props":127,"children":128},{},[129,134],{"type":30,"tag":44,"props":130,"children":131},{},[132],{"type":36,"value":133},"Couplage de technologie :",{"type":36,"value":135}," tous les services sont contraints d'utiliser le même moteur de base de données, même si certains auraient besoin d'un graph database et d'autres d'un document store.",{"type":30,"tag":38,"props":137,"children":138},{},[139,141,148],{"type":36,"value":140},"Ces couplages valent la peine d'être éliminés, mais la question est : à quel coût, et avec quelle alternative ? Et la décision de les éliminer (ou de les tolérer) mérite d'être consignée dans un ",{"type":30,"tag":142,"props":143,"children":145},"a",{"href":144},"/fr/architecture-craft/adr-architecture-decision-record",[146],{"type":36,"value":147},"Architecture Decision Record",{"type":36,"value":149}," pour que le contexte reste accessible à toute l'équipe.",{"type":30,"tag":67,"props":151,"children":152},{},[],{"type":30,"tag":71,"props":154,"children":156},{"id":155},"le-coût-réel-de-database-per-service",[157],{"type":36,"value":158},"Le coût réel de Database per Service",{"type":30,"tag":38,"props":160,"children":161},{},[162,167],{"type":30,"tag":44,"props":163,"children":164},{},[165],{"type":36,"value":166},"Complexité opérationnelle :",{"type":36,"value":168}," 10 services = 10 bases de données à provisionner, monitorer, sauvegarder, mettre à jour, et maintenir en haute disponibilité. Sur AWS, 10 instances RDS PostgreSQL coûtent entre 500 et 2 000€ par mois selon la taille, avant les coûts d'ingénierie pour les gérer.",{"type":30,"tag":38,"props":170,"children":171},{},[172,177],{"type":30,"tag":44,"props":173,"children":174},{},[175],{"type":36,"value":176},"Transactions distribuées :",{"type":36,"value":178}," sans base de données partagée, une opération qui modifie des données dans plusieurs services (créer une commande ET décrémenter le stock ET enregistrer le paiement) ne peut plus être traitée dans une transaction ACID.",{"type":30,"tag":38,"props":180,"children":181},{},[182],{"type":36,"value":183},"Il faut implémenter le pattern Saga, décrit en détail par Vernon Vaughn dans \"Implementing Domain-Driven Design\" :",{"type":30,"tag":185,"props":186,"children":188},"pre",{"code":187},"Saga chorégraphie pour la création d'une commande :\nOrderService.createOrder() → publie OrderCreated\n→ InventoryService réserve le stock → publie InventoryReserved\n→ PaymentService charge le paiement → publie PaymentProcessed\n→ OrderService confirme la commande\n\nEn cas d'échec du paiement :\n→ PaymentService publie PaymentFailed\n→ InventoryService libère la réservation\n→ OrderService annule la commande\n",[189],{"type":30,"tag":98,"props":190,"children":191},{"__ignoreMap":8},[192],{"type":36,"value":187},{"type":30,"tag":38,"props":194,"children":195},{},[196,198,204],{"type":36,"value":197},"Chaque étape peut échouer, les messages peuvent être perdus ou dupliqués, et les états intermédiaires sont difficiles à debugger. Pour renforcer la robustesse de ces flux, les ",{"type":30,"tag":142,"props":199,"children":201},{"href":200},"/fr/architecture-craft/patterns-resilience-circuit-breaker-retry",[202],{"type":36,"value":203},"patterns de résilience : circuit breaker, retry, timeout",{"type":36,"value":205}," sont indispensables dès lors que les services communiquent de manière asynchrone.",{"type":30,"tag":38,"props":207,"children":208},{},[209,214,216,222],{"type":30,"tag":44,"props":210,"children":211},{},[212],{"type":36,"value":213},"Requêtes cross-services :",{"type":36,"value":215}," une requête qui joint des données de plusieurs services (liste des commandes avec le nom du client et le stock disponible) devient une API composition : plusieurs appels HTTP en séquence ou en parallèle, avec de la logique d'agrégation en mémoire. Cette communication asynchrone entre services introduit un ",{"type":30,"tag":142,"props":217,"children":219},{"href":218},"/fr/architecture-craft/couplage-temporel-code-asynchrone",[220],{"type":36,"value":221},"couplage temporel",{"type":36,"value":223}," qu'il faut gérer explicitement, notamment avec des garanties d'idempotence et d'ordre sur les événements.",{"type":30,"tag":225,"props":226,"children":231},"cta",{"cta":227,"href":228,"title":229,"type":230},"Réserver mon diagnostic gratuit →","https://app.kamanga.fr/forms/discovery-call","Vous migrez vers les microservices et vous hésitez sur la stratégie de base de données ?","call",[232],{"type":30,"tag":38,"props":233,"children":234},{},[235],{"type":36,"value":236},"Choisir la bonne stratégie de base de données pour une architecture distribuée dépend de nombreux facteurs contextuels que j'ai appris à évaluer sur le terrain, dans la finance, les médias, la logistique. En 30 minutes, on peut évaluer les trade-offs et définir l'approche adaptée à votre situation réelle.",{"type":30,"tag":67,"props":238,"children":239},{},[],{"type":30,"tag":71,"props":241,"children":243},{"id":242},"le-cadre-de-décision-objectif",[244],{"type":36,"value":245},"Le cadre de décision objectif",{"type":30,"tag":38,"props":247,"children":248},{},[249],{"type":36,"value":250},"La question n'est pas \"devrions-nous faire Database per Service ?\", c'est \"quel niveau de couplage de base de données est acceptable dans notre contexte ?\"",{"type":30,"tag":252,"props":253,"children":254},"table",{},[255,279],{"type":30,"tag":256,"props":257,"children":258},"thead",{},[259],{"type":30,"tag":260,"props":261,"children":262},"tr",{},[263,269,274],{"type":30,"tag":264,"props":265,"children":266},"th",{},[267],{"type":36,"value":268},"Critère",{"type":30,"tag":264,"props":270,"children":271},{},[272],{"type":36,"value":273},"Favorise Database per Service",{"type":30,"tag":264,"props":275,"children":276},{},[277],{"type":36,"value":278},"Favorise Base partagée",{"type":30,"tag":280,"props":281,"children":282},"tbody",{},[283,302,320,338,356,374],{"type":30,"tag":260,"props":284,"children":285},{},[286,292,297],{"type":30,"tag":287,"props":288,"children":289},"td",{},[290],{"type":36,"value":291},"Taille de l'équipe",{"type":30,"tag":287,"props":293,"children":294},{},[295],{"type":36,"value":296},"> 15 développeurs, équipes indépendantes",{"type":30,"tag":287,"props":298,"children":299},{},[300],{"type":36,"value":301},"\u003C 15 développeurs, une seule équipe",{"type":30,"tag":260,"props":303,"children":304},{},[305,310,315],{"type":30,"tag":287,"props":306,"children":307},{},[308],{"type":36,"value":309},"Fréquence de changement de schéma",{"type":30,"tag":287,"props":311,"children":312},{},[313],{"type":36,"value":314},"Fréquente (plusieurs fois par semaine)",{"type":30,"tag":287,"props":316,"children":317},{},[318],{"type":36,"value":319},"Rare (quelques fois par mois)",{"type":30,"tag":260,"props":321,"children":322},{},[323,328,333],{"type":30,"tag":287,"props":324,"children":325},{},[326],{"type":36,"value":327},"Exigences de performance",{"type":30,"tag":287,"props":329,"children":330},{},[331],{"type":36,"value":332},"Services avec des profils d'usage très différents",{"type":30,"tag":287,"props":334,"children":335},{},[336],{"type":36,"value":337},"Profils d'usage similaires",{"type":30,"tag":260,"props":339,"children":340},{},[341,346,351],{"type":30,"tag":287,"props":342,"children":343},{},[344],{"type":36,"value":345},"Exigences de disponibilité",{"type":30,"tag":287,"props":347,"children":348},{},[349],{"type":36,"value":350},"SLAs différents par service",{"type":30,"tag":287,"props":352,"children":353},{},[354],{"type":36,"value":355},"SLA uniforme",{"type":30,"tag":260,"props":357,"children":358},{},[359,364,369],{"type":30,"tag":287,"props":360,"children":361},{},[362],{"type":36,"value":363},"Transactions cross-services",{"type":30,"tag":287,"props":365,"children":366},{},[367],{"type":36,"value":368},"Rares",{"type":30,"tag":287,"props":370,"children":371},{},[372],{"type":36,"value":373},"Fréquentes et critiques",{"type":30,"tag":260,"props":375,"children":376},{},[377,382,387],{"type":30,"tag":287,"props":378,"children":379},{},[380],{"type":36,"value":381},"Maturité opérationnelle",{"type":30,"tag":287,"props":383,"children":384},{},[385],{"type":36,"value":386},"SRE dédié, infrastructure mature",{"type":30,"tag":287,"props":388,"children":389},{},[390],{"type":36,"value":391},"Pas d'équipe infra dédiée",{"type":30,"tag":38,"props":393,"children":394},{},[395,400],{"type":30,"tag":44,"props":396,"children":397},{},[398],{"type":36,"value":399},"La règle empirique :",{"type":36,"value":401}," si les équipes qui développent les services peuvent déployer indépendamment et que les transactions cross-services sont rares, Database per Service a du sens. Sinon, le coût dépasse la valeur.",{"type":30,"tag":67,"props":403,"children":404},{},[],{"type":30,"tag":71,"props":406,"children":408},{"id":407},"les-alternatives-ignorées",[409],{"type":36,"value":410},"Les alternatives ignorées",{"type":30,"tag":38,"props":412,"children":413},{},[414],{"type":36,"value":415},"Avant de sauter à \"une base de données par service\", il existe des options intermédiaires qui réduisent le couplage sans la complexité complète.",{"type":30,"tag":38,"props":417,"children":418},{},[419],{"type":30,"tag":44,"props":420,"children":421},{},[422],{"type":36,"value":423},"Option 1 : Schema per Service (dans la même base de données)",{"type":30,"tag":38,"props":425,"children":426},{},[427],{"type":36,"value":428},"Chaque service possède son schéma (namespace) dans une base de données partagée. Le service A ne peut accéder qu'aux tables du schéma A.",{"type":30,"tag":185,"props":430,"children":434},{"code":431,"language":432,"meta":8,"className":433,"style":8},"-- Service A n'accède qu'à son schéma\nSET search_path TO ordering;\nSELECT * FROM orders;  -- → ordering.orders\n\n-- Service B n'accède qu'à son schéma\nSET search_path TO inventory;\nSELECT * FROM products;  -- → inventory.products\n","sql","language-sql shiki shiki-themes catppuccin-frappe github-dark",[435],{"type":30,"tag":98,"props":436,"children":437},{"__ignoreMap":8},[438,450,476,506,515,524,545],{"type":30,"tag":439,"props":440,"children":443},"span",{"class":441,"line":442},"line",1,[444],{"type":30,"tag":439,"props":445,"children":447},{"style":446},"--shiki-default:#737994;--shiki-default-font-style:italic;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit",[448],{"type":36,"value":449},"-- Service A n'accède qu'à son schéma\n",{"type":30,"tag":439,"props":451,"children":453},{"class":441,"line":452},2,[454,460,466,471],{"type":30,"tag":439,"props":455,"children":457},{"style":456},"--shiki-default:#CA9EE6;--shiki-dark:#F97583",[458],{"type":36,"value":459},"SET",{"type":30,"tag":439,"props":461,"children":463},{"style":462},"--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8",[464],{"type":36,"value":465}," search_path ",{"type":30,"tag":439,"props":467,"children":468},{"style":456},[469],{"type":36,"value":470},"TO",{"type":30,"tag":439,"props":472,"children":473},{"style":462},[474],{"type":36,"value":475}," ordering;\n",{"type":30,"tag":439,"props":477,"children":479},{"class":441,"line":478},3,[480,485,491,496,501],{"type":30,"tag":439,"props":481,"children":482},{"style":456},[483],{"type":36,"value":484},"SELECT",{"type":30,"tag":439,"props":486,"children":488},{"style":487},"--shiki-default:#81C8BE;--shiki-dark:#F97583",[489],{"type":36,"value":490}," *",{"type":30,"tag":439,"props":492,"children":493},{"style":456},[494],{"type":36,"value":495}," FROM",{"type":30,"tag":439,"props":497,"children":498},{"style":462},[499],{"type":36,"value":500}," orders;  ",{"type":30,"tag":439,"props":502,"children":503},{"style":446},[504],{"type":36,"value":505},"-- → ordering.orders\n",{"type":30,"tag":439,"props":507,"children":509},{"class":441,"line":508},4,[510],{"type":30,"tag":439,"props":511,"children":512},{"emptyLinePlaceholder":13},[513],{"type":36,"value":514},"\n",{"type":30,"tag":439,"props":516,"children":518},{"class":441,"line":517},5,[519],{"type":30,"tag":439,"props":520,"children":521},{"style":446},[522],{"type":36,"value":523},"-- Service B n'accède qu'à son schéma\n",{"type":30,"tag":439,"props":525,"children":527},{"class":441,"line":526},6,[528,532,536,540],{"type":30,"tag":439,"props":529,"children":530},{"style":456},[531],{"type":36,"value":459},{"type":30,"tag":439,"props":533,"children":534},{"style":462},[535],{"type":36,"value":465},{"type":30,"tag":439,"props":537,"children":538},{"style":456},[539],{"type":36,"value":470},{"type":30,"tag":439,"props":541,"children":542},{"style":462},[543],{"type":36,"value":544}," inventory;\n",{"type":30,"tag":439,"props":546,"children":548},{"class":441,"line":547},7,[549,553,557,561,566],{"type":30,"tag":439,"props":550,"children":551},{"style":456},[552],{"type":36,"value":484},{"type":30,"tag":439,"props":554,"children":555},{"style":487},[556],{"type":36,"value":490},{"type":30,"tag":439,"props":558,"children":559},{"style":456},[560],{"type":36,"value":495},{"type":30,"tag":439,"props":562,"children":563},{"style":462},[564],{"type":36,"value":565}," products;  ",{"type":30,"tag":439,"props":567,"children":568},{"style":446},[569],{"type":36,"value":570},"-- → inventory.products\n",{"type":30,"tag":38,"props":572,"children":573},{},[574],{"type":36,"value":575},"Avantages : les transactions ACID restent possibles si nécessaire. Complexité opérationnelle minimale (une seule base de données).",{"type":30,"tag":38,"props":577,"children":578},{},[579],{"type":30,"tag":44,"props":580,"children":581},{},[582],{"type":36,"value":583},"Option 2 : Read replicas dédiées par service",{"type":30,"tag":38,"props":585,"children":586},{},[587],{"type":36,"value":588},"La base de données principale est partagée pour les écritures, mais chaque service lit depuis sa propre replica read-only synchronisée. Utile quand le problème principal est la contention de lecture.",{"type":30,"tag":38,"props":590,"children":591},{},[592],{"type":30,"tag":44,"props":593,"children":594},{},[595],{"type":36,"value":596},"Option 3 : CQRS sans séparation de base",{"type":30,"tag":38,"props":598,"children":599},{},[600],{"type":36,"value":601},"Séparer les modèles de lecture et d'écriture sans nécessairement avoir des bases de données séparées. Les requêtes complexes lisent des vues matérialisées maintenues à jour par des événements.",{"type":30,"tag":67,"props":603,"children":604},{},[],{"type":30,"tag":71,"props":606,"children":608},{"id":607},"quand-migrer-vers-database-per-service",[609],{"type":36,"value":610},"Quand migrer vers Database per Service",{"type":30,"tag":38,"props":612,"children":613},{},[614],{"type":30,"tag":44,"props":615,"children":616},{},[617],{"type":36,"value":618},"Les signaux que la base partagée devient un problème :",{"type":30,"tag":620,"props":621,"children":622},"ul",{},[623,629,634,639],{"type":30,"tag":624,"props":625,"children":626},"li",{},[627],{"type":36,"value":628},"Les migrations de base de données nécessitent de coordonner 3 équipes ou plus",{"type":30,"tag":624,"props":630,"children":631},{},[632],{"type":36,"value":633},"Un service lent dégrade régulièrement les performances des autres",{"type":30,"tag":624,"props":635,"children":636},{},[637],{"type":36,"value":638},"Deux services ont des besoins contradictoires sur le schéma d'une table partagée",{"type":30,"tag":624,"props":640,"children":641},{},[642],{"type":36,"value":643},"L'équipe veut utiliser un moteur de base de données différent pour un service spécifique",{"type":30,"tag":38,"props":645,"children":646},{},[647,652],{"type":30,"tag":44,"props":648,"children":649},{},[650],{"type":36,"value":651},"La migration progressive :",{"type":36,"value":653}," commencer par les tables du service le plus indépendant. Migrer la table, mettre en place la synchronisation des données si nécessaire (CDC avec Debezium, événements de domaine), valider, puis passer à la table suivante.",{"type":30,"tag":185,"props":655,"children":657},{"code":656},"Plan de migration en 4 phases :\nPhase 1 : service de notifications (aucune dépendance cross-service)\nPhase 2 : service de recherche (lecture seule, pas d'écriture cross-service)\nPhase 3 : service de catalogue produit (écriture rarement liée aux autres)\nPhase 4 : service de commandes (transactions complexes — laisser pour dernier)\n",[658],{"type":30,"tag":98,"props":659,"children":660},{"__ignoreMap":8},[661],{"type":36,"value":656},{"type":30,"tag":67,"props":663,"children":664},{},[],{"type":30,"tag":71,"props":666,"children":668},{"id":667},"le-cas-particulier-du-polyglot-persistence",[669],{"type":36,"value":670},"Le cas particulier du polyglot persistence",{"type":30,"tag":38,"props":672,"children":673},{},[674],{"type":36,"value":675},"Database per Service devient moins coûteux quand les services utilisent des bases de données managées (DynamoDB, MongoDB Atlas, Redis Cloud) avec une facturation à l'usage. Le coût opérationnel est absorbé par le fournisseur.",{"type":30,"tag":38,"props":677,"children":678},{},[679],{"type":36,"value":680},"Le pattern polyglot persistence (chaque service utilise le moteur adapté à ses besoins) ne vaut sa complexité que si les besoins sont vraiment distincts et que l'équipe a la maturité opérationnelle pour gérer plusieurs moteurs.",{"type":30,"tag":620,"props":682,"children":683},{},[684,689,694,699],{"type":30,"tag":624,"props":685,"children":686},{},[687],{"type":36,"value":688},"Service de recherche → Elasticsearch",{"type":30,"tag":624,"props":690,"children":691},{},[692],{"type":36,"value":693},"Service de sessions → Redis",{"type":30,"tag":624,"props":695,"children":696},{},[697],{"type":36,"value":698},"Service de catalogue → MongoDB (documents flexibles)",{"type":30,"tag":624,"props":700,"children":701},{},[702],{"type":36,"value":703},"Service de commandes → PostgreSQL (transactions ACID)",{"type":30,"tag":67,"props":705,"children":706},{},[],{"type":30,"tag":71,"props":708,"children":710},{"id":709},"faq-sur-database-per-service",[711],{"type":36,"value":712},"FAQ sur Database per Service",{"type":30,"tag":714,"props":715,"children":716},"details",{},[717,723],{"type":30,"tag":718,"props":719,"children":720},"summary",{},[721],{"type":36,"value":722},"1. Comment gérer la cohérence des données entre services sans transactions distribuées ?",{"type":30,"tag":38,"props":724,"children":725},{},[726],{"type":36,"value":727},"Eventual consistency avec compensation. Accepter que les données ne soient pas instantanément cohérentes entre services, seulement éventuellement cohérentes. Pour les cas où une cohérence forte est nécessaire, utiliser le pattern Outbox : écrire l'événement dans la même transaction que la donnée, puis publier l'événement de façon asynchrone. Pour les cas d'échec, implémenter des compensating transactions explicites plutôt que des rollbacks automatiques.",{"type":30,"tag":714,"props":729,"children":730},{},[731,736],{"type":30,"tag":718,"props":732,"children":733},{},[734],{"type":36,"value":735},"2. Peut-on utiliser des transactions distribuées (2PC) à la place des Sagas ?",{"type":30,"tag":38,"props":737,"children":738},{},[739],{"type":36,"value":740},"Techniquement oui, mais déconseillé. Le Two-Phase Commit est lent (lock pendant la phase de préparation), fragile (coordinator failure = système bloqué), et complexe à implémenter correctement. Les Sagas sont plus complexes à concevoir mais plus robustes en production. La recommandation de Sam Newman et de l'industrie : éviter 2PC, préférer les Sagas ou revoir l'architecture pour réduire les transactions cross-services.",{"type":30,"tag":714,"props":742,"children":743},{},[744,749],{"type":30,"tag":718,"props":745,"children":746},{},[747],{"type":36,"value":748},"3. Comment gérer les reportings qui nécessitent des données de plusieurs services ?",{"type":30,"tag":38,"props":750,"children":751},{},[752],{"type":36,"value":753},"Data warehouse ou OLAP dédié. Chaque service publie ses événements vers un pipeline de données (Kafka → Spark/Flink → Data Warehouse). Les analyses et rapports lisent le data warehouse, pas les bases des services. C'est le principe CQRS à l'échelle de l'architecture : les services gèrent les écritures, le data warehouse gère les lectures analytiques complexes.",{"type":30,"tag":714,"props":755,"children":756},{},[757,762],{"type":30,"tag":718,"props":758,"children":759},{},[760],{"type":36,"value":761},"4. Quel outil utiliser pour la synchronisation de données entre services ?",{"type":30,"tag":38,"props":763,"children":764},{},[765],{"type":36,"value":766},"Change Data Capture (CDC) avec Debezium : il capture les changements PostgreSQL/MySQL en temps réel et les publie sur Kafka. Pour des cas plus simples : événements de domaine publiés sur une queue à chaque changement d'état. L'approche CDC est plus robuste (aucun changement applicatif requis) mais plus complexe à opérer. Les événements de domaine sont plus simples mais nécessitent une discipline applicative.",{"type":30,"tag":714,"props":768,"children":769},{},[770,775],{"type":30,"tag":718,"props":771,"children":772},{},[773],{"type":36,"value":774},"5. Database per Service est-il compatible avec les architectures serverless (Lambda, Cloud Functions) ?",{"type":30,"tag":38,"props":776,"children":777},{},[778],{"type":36,"value":779},"Oui, et c'est souvent plus simple. Les bases de données managées à l'usage (DynamoDB, Firestore, Aurora Serverless) s'adaptent naturellement au modèle serverless : pas de pool de connexions à gérer, facturation à la requête. Le principal défi est la gestion des connexions (Lambda peut créer des milliers de connexions simultanées), résolu par des proxy de connexions comme RDS Proxy pour PostgreSQL/MySQL.",{"type":30,"tag":67,"props":781,"children":782},{},[],{"type":30,"tag":225,"props":784,"children":789},{"cta":785,"href":786,"title":787,"type":788},"Faire mon auto-évaluation →","/ema","Ressource gratuite : Engineering Maturity Self-Assessment","resource",[790],{"type":30,"tag":38,"props":791,"children":792},{},[793],{"type":36,"value":794},"L'Engineering Maturity Self-Assessment couvre le domaine Architecture Distribuée : évaluez votre maturité sur le découpage des services, la gestion des données, et la résilience. Score et plan d'action en 10 minutes.",{"type":30,"tag":796,"props":797,"children":798},"style",{},[799],{"type":36,"value":800},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":8,"searchDepth":452,"depth":452,"links":802},[803,804,805,806,807,808,809],{"id":73,"depth":452,"text":76},{"id":155,"depth":452,"text":158},{"id":242,"depth":452,"text":245},{"id":407,"depth":452,"text":410},{"id":607,"depth":452,"text":610},{"id":667,"depth":452,"text":670},{"id":709,"depth":452,"text":712},"markdown","content:fr:architecture-craft:database-per-service-microservices.md","content","fr/architecture-craft/database-per-service-microservices.md","fr/architecture-craft/database-per-service-microservices","md",{"_path":200,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":817,"description":818,"id":819,"date":820,"listed":13,"nocomments":7,"hidden":7,"categories":821,"tags":822,"--cover":826,"readingTime":827,"body":832,"_type":810,"_id":2463,"_source":812,"_file":2464,"_stem":2465,"_extension":815},"Patterns de résilience : circuit breaker, retry, timeout","Les 3 patterns de résilience fondamentaux que tout système distribué doit implémenter. Sans eux, la défaillance d'un service cascade et fait tomber toute l'architecture.",25,"2026-03-02",[6],[823,824,825,18],"Résilience","Circuit Breaker","Retry","covers/articles/patterns-resilience-circuit-breaker.jpg",{"text":828,"minutes":829,"time":830,"words":831},"7 min read",6.985,419100,1397,{"type":27,"children":833,"toc":2454},[834,839,844,849,854,859,862,868,879,884,896,899,905,910,920,928,946,1170,1180,1183,1189,1194,1204,1580,1588,1601,1610,1613,1619,1624,1632,1642,1652,1662,1990,2255,2258,2264,2274,2284,2302,2307,2310,2316,2350,2355,2358,2364,2384,2397,2418,2439,2442,2450],{"type":30,"tag":31,"props":835,"children":837},{"id":836},"patterns-de-résilience-circuit-breaker-retry-timeout",[838],{"type":36,"value":817},{"type":30,"tag":38,"props":840,"children":841},{},[842],{"type":36,"value":843},"J'accompagnais un client dans le secteur du retail en ligne (25 développeurs). En six mois, trois incidents P1, à chaque fois pendant des pics de trafic. Le service de recommandations devenait lent, les threads du service produit s'accumulaient en attente, le pool de connexions s'épuisait, et le service produit tombait à son tour. La homepage devenait indisponible.",{"type":30,"tag":38,"props":845,"children":846},{},[847],{"type":36,"value":848},"Le service de recommandations avait une excuse valable : les pics de charge. Le service produit n'en avait pas. Il n'avait simplement aucun mécanisme pour se protéger d'un voisin défaillant.",{"type":30,"tag":38,"props":850,"children":851},{},[852],{"type":36,"value":853},"Deux heures de développement pour ajouter un timeout. Deux jours pour le circuit breaker. Zéro incident P1 lié aux recommandations depuis lors. Les recommandations continuent de tomber lors des pics, mais ça reste isolé.",{"type":30,"tag":38,"props":855,"children":856},{},[857],{"type":36,"value":858},"C'est ce que les patterns de résilience font : ils n'éliminent pas les pannes, ils empêchent qu'une panne locale devienne un effondrement global.",{"type":30,"tag":67,"props":860,"children":861},{},[],{"type":30,"tag":71,"props":863,"children":865},{"id":864},"la-cascade-failure-pourquoi-les-systèmes-distribués-seffondrent-en-bloc",[866],{"type":36,"value":867},"La cascade failure : pourquoi les systèmes distribués s'effondrent en bloc",{"type":30,"tag":38,"props":869,"children":870},{},[871,873,877],{"type":36,"value":872},"Sans mécanisme de protection, les appels vers des services externes dans un système distribué ont une propriété dangereuse : si le service cible ralentit, les appelants attendent, leurs ressources se consomment, et ils deviennent eux-mêmes défaillants. Ce phénomène est aggravé par le ",{"type":30,"tag":142,"props":874,"children":875},{"href":218},[876],{"type":36,"value":221},{"type":36,"value":878}," entre services, qui crée des dépendances implicites d'ordre ou de timing difficiles à détecter jusqu'en production.",{"type":30,"tag":38,"props":880,"children":881},{},[882],{"type":36,"value":883},"Michael Nygard a documenté ce pattern en détail dans \"Release It!\" (2007), l'ouvrage de référence sur la résilience des systèmes en production. Sa conclusion : la stabilité ne se construit pas par l'optimisme (espérer que les services tiers restent disponibles), mais par la conception défensive (prévoir leur défaillance et la gérer).",{"type":30,"tag":38,"props":885,"children":886},{},[887,889,894],{"type":36,"value":888},"Selon Gartner, une heure de downtime coûte en moyenne ",{"type":30,"tag":44,"props":890,"children":891},{},[892],{"type":36,"value":893},"300 000€",{"type":36,"value":895}," pour une application business critique. Les 3 patterns décrits ici sont des assurances contre ce coût.",{"type":30,"tag":67,"props":897,"children":898},{},[],{"type":30,"tag":71,"props":900,"children":902},{"id":901},"pattern-1-timeout",[903],{"type":36,"value":904},"Pattern 1 : Timeout",{"type":30,"tag":38,"props":906,"children":907},{},[908],{"type":36,"value":909},"Le timeout est le premier niveau de protection, et le plus souvent absent. Un appel vers un service externe sans timeout peut attendre indéfiniment, bloquant les ressources de l'appelant.",{"type":30,"tag":38,"props":911,"children":912},{},[913,918],{"type":30,"tag":44,"props":914,"children":915},{},[916],{"type":36,"value":917},"Principe :",{"type":36,"value":919}," tout appel vers un service externe (HTTP, base de données, cache, message broker) doit avoir un timeout explicite défini dans le code. Si le service ne répond pas dans ce délai, l'appel est considéré comme échoué et les ressources sont libérées.",{"type":30,"tag":38,"props":921,"children":922},{},[923],{"type":30,"tag":44,"props":924,"children":925},{},[926],{"type":36,"value":927},"Comment définir la valeur du timeout :",{"type":30,"tag":620,"props":929,"children":930},{},[931,936,941],{"type":30,"tag":624,"props":932,"children":933},{},[934],{"type":36,"value":935},"Mesurer le p99 (99ème percentile) de la latence du service cible sur les 30 derniers jours",{"type":30,"tag":624,"props":937,"children":938},{},[939],{"type":36,"value":940},"Multiplier par 2 à 3 pour le timeout",{"type":30,"tag":624,"props":942,"children":943},{},[944],{"type":36,"value":945},"Ne jamais utiliser la valeur par défaut du client HTTP (souvent 30 secondes à 2 minutes, beaucoup trop long)",{"type":30,"tag":185,"props":947,"children":951},{"className":948,"code":949,"language":950,"meta":8,"style":8},"language-java shiki shiki-themes catppuccin-frappe github-dark","// Exemple avec OkHttp (Java)\nOkHttpClient client = new OkHttpClient.Builder()\n    .connectTimeout(2, TimeUnit.SECONDS)  // temps max pour établir la connexion\n    .readTimeout(5, TimeUnit.SECONDS)     // temps max pour recevoir la réponse\n    .writeTimeout(5, TimeUnit.SECONDS)    // temps max pour envoyer la requête\n    .build();\n","java",[952],{"type":30,"tag":98,"props":953,"children":954},{"__ignoreMap":8},[955,963,1009,1062,1108,1153],{"type":30,"tag":439,"props":956,"children":957},{"class":441,"line":442},[958],{"type":30,"tag":439,"props":959,"children":960},{"style":446},[961],{"type":36,"value":962},"// Exemple avec OkHttp (Java)\n",{"type":30,"tag":439,"props":964,"children":965},{"class":441,"line":452},[966,972,977,982,987,992,998,1004],{"type":30,"tag":439,"props":967,"children":969},{"style":968},"--shiki-default:#CA9EE6;--shiki-dark:#E1E4E8",[970],{"type":36,"value":971},"OkHttpClient",{"type":30,"tag":439,"props":973,"children":974},{"style":462},[975],{"type":36,"value":976}," client ",{"type":30,"tag":439,"props":978,"children":979},{"style":487},[980],{"type":36,"value":981},"=",{"type":30,"tag":439,"props":983,"children":984},{"style":456},[985],{"type":36,"value":986}," new",{"type":30,"tag":439,"props":988,"children":989},{"style":462},[990],{"type":36,"value":991}," OkHttpClient",{"type":30,"tag":439,"props":993,"children":995},{"style":994},"--shiki-default:#949CBB;--shiki-dark:#E1E4E8",[996],{"type":36,"value":997},".",{"type":30,"tag":439,"props":999,"children":1001},{"style":1000},"--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[1002],{"type":36,"value":1003},"Builder",{"type":30,"tag":439,"props":1005,"children":1006},{"style":994},[1007],{"type":36,"value":1008},"()\n",{"type":30,"tag":439,"props":1010,"children":1011},{"class":441,"line":478},[1012,1017,1022,1027,1033,1038,1043,1047,1052,1057],{"type":30,"tag":439,"props":1013,"children":1014},{"style":994},[1015],{"type":36,"value":1016},"    .",{"type":30,"tag":439,"props":1018,"children":1019},{"style":1000},[1020],{"type":36,"value":1021},"connectTimeout",{"type":30,"tag":439,"props":1023,"children":1024},{"style":994},[1025],{"type":36,"value":1026},"(",{"type":30,"tag":439,"props":1028,"children":1030},{"style":1029},"--shiki-default:#EF9F76;--shiki-dark:#79B8FF",[1031],{"type":36,"value":1032},"2",{"type":30,"tag":439,"props":1034,"children":1035},{"style":994},[1036],{"type":36,"value":1037},",",{"type":30,"tag":439,"props":1039,"children":1040},{"style":462},[1041],{"type":36,"value":1042}," TimeUnit",{"type":30,"tag":439,"props":1044,"children":1045},{"style":994},[1046],{"type":36,"value":997},{"type":30,"tag":439,"props":1048,"children":1049},{"style":462},[1050],{"type":36,"value":1051},"SECONDS",{"type":30,"tag":439,"props":1053,"children":1054},{"style":994},[1055],{"type":36,"value":1056},")",{"type":30,"tag":439,"props":1058,"children":1059},{"style":446},[1060],{"type":36,"value":1061},"  // temps max pour établir la connexion\n",{"type":30,"tag":439,"props":1063,"children":1064},{"class":441,"line":508},[1065,1069,1074,1078,1083,1087,1091,1095,1099,1103],{"type":30,"tag":439,"props":1066,"children":1067},{"style":994},[1068],{"type":36,"value":1016},{"type":30,"tag":439,"props":1070,"children":1071},{"style":1000},[1072],{"type":36,"value":1073},"readTimeout",{"type":30,"tag":439,"props":1075,"children":1076},{"style":994},[1077],{"type":36,"value":1026},{"type":30,"tag":439,"props":1079,"children":1080},{"style":1029},[1081],{"type":36,"value":1082},"5",{"type":30,"tag":439,"props":1084,"children":1085},{"style":994},[1086],{"type":36,"value":1037},{"type":30,"tag":439,"props":1088,"children":1089},{"style":462},[1090],{"type":36,"value":1042},{"type":30,"tag":439,"props":1092,"children":1093},{"style":994},[1094],{"type":36,"value":997},{"type":30,"tag":439,"props":1096,"children":1097},{"style":462},[1098],{"type":36,"value":1051},{"type":30,"tag":439,"props":1100,"children":1101},{"style":994},[1102],{"type":36,"value":1056},{"type":30,"tag":439,"props":1104,"children":1105},{"style":446},[1106],{"type":36,"value":1107},"     // temps max pour recevoir la réponse\n",{"type":30,"tag":439,"props":1109,"children":1110},{"class":441,"line":517},[1111,1115,1120,1124,1128,1132,1136,1140,1144,1148],{"type":30,"tag":439,"props":1112,"children":1113},{"style":994},[1114],{"type":36,"value":1016},{"type":30,"tag":439,"props":1116,"children":1117},{"style":1000},[1118],{"type":36,"value":1119},"writeTimeout",{"type":30,"tag":439,"props":1121,"children":1122},{"style":994},[1123],{"type":36,"value":1026},{"type":30,"tag":439,"props":1125,"children":1126},{"style":1029},[1127],{"type":36,"value":1082},{"type":30,"tag":439,"props":1129,"children":1130},{"style":994},[1131],{"type":36,"value":1037},{"type":30,"tag":439,"props":1133,"children":1134},{"style":462},[1135],{"type":36,"value":1042},{"type":30,"tag":439,"props":1137,"children":1138},{"style":994},[1139],{"type":36,"value":997},{"type":30,"tag":439,"props":1141,"children":1142},{"style":462},[1143],{"type":36,"value":1051},{"type":30,"tag":439,"props":1145,"children":1146},{"style":994},[1147],{"type":36,"value":1056},{"type":30,"tag":439,"props":1149,"children":1150},{"style":446},[1151],{"type":36,"value":1152},"    // temps max pour envoyer la requête\n",{"type":30,"tag":439,"props":1154,"children":1155},{"class":441,"line":526},[1156,1160,1165],{"type":30,"tag":439,"props":1157,"children":1158},{"style":994},[1159],{"type":36,"value":1016},{"type":30,"tag":439,"props":1161,"children":1162},{"style":1000},[1163],{"type":36,"value":1164},"build",{"type":30,"tag":439,"props":1166,"children":1167},{"style":994},[1168],{"type":36,"value":1169},"();\n",{"type":30,"tag":38,"props":1171,"children":1172},{},[1173,1178],{"type":30,"tag":44,"props":1174,"children":1175},{},[1176],{"type":36,"value":1177},"À quelle couche définir le timeout :",{"type":36,"value":1179}," aussi près que possible de l'appel externe. Un timeout au niveau de l'API gateway seul ne protège pas les services internes.",{"type":30,"tag":67,"props":1181,"children":1182},{},[],{"type":30,"tag":71,"props":1184,"children":1186},{"id":1185},"pattern-2-retry-avec-backoff-exponentiel",[1187],{"type":36,"value":1188},"Pattern 2 : Retry avec backoff exponentiel",{"type":30,"tag":38,"props":1190,"children":1191},{},[1192],{"type":36,"value":1193},"Un service peut échouer de façon transitoire : surcharge momentanée, redémarrage d'instance, pic de latence. Un retry permet de retenter l'opération après un délai, sans inonder le service défaillant de requêtes supplémentaires.",{"type":30,"tag":38,"props":1195,"children":1196},{},[1197,1202],{"type":30,"tag":44,"props":1198,"children":1199},{},[1200],{"type":36,"value":1201},"Principe du backoff exponentiel :",{"type":36,"value":1203}," le délai entre les tentatives augmente exponentiellement. Avec un jitter (variation aléatoire) pour éviter que tous les appelants retentent exactement au même moment, ce qui recréerait la surcharge qu'on cherche à éviter.",{"type":30,"tag":185,"props":1205,"children":1209},{"className":1206,"code":1207,"language":1208,"meta":8,"style":8},"language-python shiki shiki-themes catppuccin-frappe github-dark","import time\nimport random\n\ndef call_with_retry(func, max_retries=3, base_delay=0.1):\n    for attempt in range(max_retries):\n        try:\n            return func()\n        except TransientError as e:\n            if attempt == max_retries - 1:\n                raise  # dernière tentative — propager l'erreur\n            delay = base_delay * (2 ** attempt) + random.uniform(0, 0.1)  # jitter\n            time.sleep(delay)\n","python",[1210],{"type":30,"tag":98,"props":1211,"children":1212},{"__ignoreMap":8},[1213,1226,1238,1245,1309,1346,1359,1377,1405,1442,1456,1548],{"type":30,"tag":439,"props":1214,"children":1215},{"class":441,"line":442},[1216,1221],{"type":30,"tag":439,"props":1217,"children":1218},{"style":456},[1219],{"type":36,"value":1220},"import",{"type":30,"tag":439,"props":1222,"children":1223},{"style":462},[1224],{"type":36,"value":1225}," time\n",{"type":30,"tag":439,"props":1227,"children":1228},{"class":441,"line":452},[1229,1233],{"type":30,"tag":439,"props":1230,"children":1231},{"style":456},[1232],{"type":36,"value":1220},{"type":30,"tag":439,"props":1234,"children":1235},{"style":462},[1236],{"type":36,"value":1237}," random\n",{"type":30,"tag":439,"props":1239,"children":1240},{"class":441,"line":478},[1241],{"type":30,"tag":439,"props":1242,"children":1243},{"emptyLinePlaceholder":13},[1244],{"type":36,"value":514},{"type":30,"tag":439,"props":1246,"children":1247},{"class":441,"line":508},[1248,1253,1258,1262,1268,1272,1277,1281,1286,1290,1295,1299,1304],{"type":30,"tag":439,"props":1249,"children":1250},{"style":456},[1251],{"type":36,"value":1252},"def",{"type":30,"tag":439,"props":1254,"children":1255},{"style":1000},[1256],{"type":36,"value":1257}," call_with_retry",{"type":30,"tag":439,"props":1259,"children":1260},{"style":994},[1261],{"type":36,"value":1026},{"type":30,"tag":439,"props":1263,"children":1265},{"style":1264},"--shiki-default:#EA999C;--shiki-default-font-style:italic;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit",[1266],{"type":36,"value":1267},"func",{"type":30,"tag":439,"props":1269,"children":1270},{"style":994},[1271],{"type":36,"value":1037},{"type":30,"tag":439,"props":1273,"children":1274},{"style":1264},[1275],{"type":36,"value":1276}," max_retries",{"type":30,"tag":439,"props":1278,"children":1279},{"style":487},[1280],{"type":36,"value":981},{"type":30,"tag":439,"props":1282,"children":1283},{"style":1029},[1284],{"type":36,"value":1285},"3",{"type":30,"tag":439,"props":1287,"children":1288},{"style":994},[1289],{"type":36,"value":1037},{"type":30,"tag":439,"props":1291,"children":1292},{"style":1264},[1293],{"type":36,"value":1294}," base_delay",{"type":30,"tag":439,"props":1296,"children":1297},{"style":487},[1298],{"type":36,"value":981},{"type":30,"tag":439,"props":1300,"children":1301},{"style":1029},[1302],{"type":36,"value":1303},"0.1",{"type":30,"tag":439,"props":1305,"children":1306},{"style":994},[1307],{"type":36,"value":1308},"):\n",{"type":30,"tag":439,"props":1310,"children":1311},{"class":441,"line":517},[1312,1317,1322,1327,1333,1337,1342],{"type":30,"tag":439,"props":1313,"children":1314},{"style":456},[1315],{"type":36,"value":1316},"    for",{"type":30,"tag":439,"props":1318,"children":1319},{"style":462},[1320],{"type":36,"value":1321}," attempt ",{"type":30,"tag":439,"props":1323,"children":1324},{"style":456},[1325],{"type":36,"value":1326},"in",{"type":30,"tag":439,"props":1328,"children":1330},{"style":1329},"--shiki-default:#EF9F76;--shiki-default-font-style:italic;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit",[1331],{"type":36,"value":1332}," range",{"type":30,"tag":439,"props":1334,"children":1335},{"style":994},[1336],{"type":36,"value":1026},{"type":30,"tag":439,"props":1338,"children":1339},{"style":462},[1340],{"type":36,"value":1341},"max_retries",{"type":30,"tag":439,"props":1343,"children":1344},{"style":994},[1345],{"type":36,"value":1308},{"type":30,"tag":439,"props":1347,"children":1348},{"class":441,"line":526},[1349,1354],{"type":30,"tag":439,"props":1350,"children":1351},{"style":456},[1352],{"type":36,"value":1353},"        try",{"type":30,"tag":439,"props":1355,"children":1356},{"style":994},[1357],{"type":36,"value":1358},":\n",{"type":30,"tag":439,"props":1360,"children":1361},{"class":441,"line":547},[1362,1367,1373],{"type":30,"tag":439,"props":1363,"children":1364},{"style":456},[1365],{"type":36,"value":1366},"            return",{"type":30,"tag":439,"props":1368,"children":1370},{"style":1369},"--shiki-default:#8CAAEE;--shiki-dark:#E1E4E8",[1371],{"type":36,"value":1372}," func",{"type":30,"tag":439,"props":1374,"children":1375},{"style":994},[1376],{"type":36,"value":1008},{"type":30,"tag":439,"props":1378,"children":1380},{"class":441,"line":1379},8,[1381,1386,1391,1396,1401],{"type":30,"tag":439,"props":1382,"children":1383},{"style":456},[1384],{"type":36,"value":1385},"        except",{"type":30,"tag":439,"props":1387,"children":1388},{"style":462},[1389],{"type":36,"value":1390}," TransientError ",{"type":30,"tag":439,"props":1392,"children":1393},{"style":456},[1394],{"type":36,"value":1395},"as",{"type":30,"tag":439,"props":1397,"children":1398},{"style":462},[1399],{"type":36,"value":1400}," e",{"type":30,"tag":439,"props":1402,"children":1403},{"style":994},[1404],{"type":36,"value":1358},{"type":30,"tag":439,"props":1406,"children":1408},{"class":441,"line":1407},9,[1409,1414,1418,1423,1428,1433,1438],{"type":30,"tag":439,"props":1410,"children":1411},{"style":456},[1412],{"type":36,"value":1413},"            if",{"type":30,"tag":439,"props":1415,"children":1416},{"style":462},[1417],{"type":36,"value":1321},{"type":30,"tag":439,"props":1419,"children":1420},{"style":487},[1421],{"type":36,"value":1422},"==",{"type":30,"tag":439,"props":1424,"children":1425},{"style":462},[1426],{"type":36,"value":1427}," max_retries ",{"type":30,"tag":439,"props":1429,"children":1430},{"style":487},[1431],{"type":36,"value":1432},"-",{"type":30,"tag":439,"props":1434,"children":1435},{"style":1029},[1436],{"type":36,"value":1437}," 1",{"type":30,"tag":439,"props":1439,"children":1440},{"style":994},[1441],{"type":36,"value":1358},{"type":30,"tag":439,"props":1443,"children":1445},{"class":441,"line":1444},10,[1446,1451],{"type":30,"tag":439,"props":1447,"children":1448},{"style":456},[1449],{"type":36,"value":1450},"                raise",{"type":30,"tag":439,"props":1452,"children":1453},{"style":446},[1454],{"type":36,"value":1455},"  # dernière tentative — propager l'erreur\n",{"type":30,"tag":439,"props":1457,"children":1459},{"class":441,"line":1458},11,[1460,1465,1469,1474,1479,1484,1488,1493,1498,1502,1507,1512,1516,1521,1525,1530,1534,1539,1543],{"type":30,"tag":439,"props":1461,"children":1462},{"style":462},[1463],{"type":36,"value":1464},"            delay ",{"type":30,"tag":439,"props":1466,"children":1467},{"style":487},[1468],{"type":36,"value":981},{"type":30,"tag":439,"props":1470,"children":1471},{"style":462},[1472],{"type":36,"value":1473}," base_delay ",{"type":30,"tag":439,"props":1475,"children":1476},{"style":487},[1477],{"type":36,"value":1478},"*",{"type":30,"tag":439,"props":1480,"children":1481},{"style":994},[1482],{"type":36,"value":1483}," (",{"type":30,"tag":439,"props":1485,"children":1486},{"style":1029},[1487],{"type":36,"value":1032},{"type":30,"tag":439,"props":1489,"children":1490},{"style":487},[1491],{"type":36,"value":1492}," **",{"type":30,"tag":439,"props":1494,"children":1495},{"style":462},[1496],{"type":36,"value":1497}," attempt",{"type":30,"tag":439,"props":1499,"children":1500},{"style":994},[1501],{"type":36,"value":1056},{"type":30,"tag":439,"props":1503,"children":1504},{"style":487},[1505],{"type":36,"value":1506}," +",{"type":30,"tag":439,"props":1508,"children":1509},{"style":462},[1510],{"type":36,"value":1511}," random",{"type":30,"tag":439,"props":1513,"children":1514},{"style":994},[1515],{"type":36,"value":997},{"type":30,"tag":439,"props":1517,"children":1518},{"style":1369},[1519],{"type":36,"value":1520},"uniform",{"type":30,"tag":439,"props":1522,"children":1523},{"style":994},[1524],{"type":36,"value":1026},{"type":30,"tag":439,"props":1526,"children":1527},{"style":1029},[1528],{"type":36,"value":1529},"0",{"type":30,"tag":439,"props":1531,"children":1532},{"style":994},[1533],{"type":36,"value":1037},{"type":30,"tag":439,"props":1535,"children":1536},{"style":1029},[1537],{"type":36,"value":1538}," 0.1",{"type":30,"tag":439,"props":1540,"children":1541},{"style":994},[1542],{"type":36,"value":1056},{"type":30,"tag":439,"props":1544,"children":1545},{"style":446},[1546],{"type":36,"value":1547},"  # jitter\n",{"type":30,"tag":439,"props":1549,"children":1551},{"class":441,"line":1550},12,[1552,1557,1561,1566,1570,1575],{"type":30,"tag":439,"props":1553,"children":1554},{"style":462},[1555],{"type":36,"value":1556},"            time",{"type":30,"tag":439,"props":1558,"children":1559},{"style":994},[1560],{"type":36,"value":997},{"type":30,"tag":439,"props":1562,"children":1563},{"style":1369},[1564],{"type":36,"value":1565},"sleep",{"type":30,"tag":439,"props":1567,"children":1568},{"style":994},[1569],{"type":36,"value":1026},{"type":30,"tag":439,"props":1571,"children":1572},{"style":462},[1573],{"type":36,"value":1574},"delay",{"type":30,"tag":439,"props":1576,"children":1577},{"style":994},[1578],{"type":36,"value":1579},")\n",{"type":30,"tag":38,"props":1581,"children":1582},{},[1583],{"type":30,"tag":44,"props":1584,"children":1585},{},[1586],{"type":36,"value":1587},"Quand ne pas retenter :",{"type":30,"tag":620,"props":1589,"children":1590},{},[1591,1596],{"type":30,"tag":624,"props":1592,"children":1593},{},[1594],{"type":36,"value":1595},"Erreurs non-transientes (404, 401, 403, validation error) : retenter ne changera rien",{"type":30,"tag":624,"props":1597,"children":1598},{},[1599],{"type":36,"value":1600},"Opérations non-idempotentes : retenter peut dupliquer l'effet (créer deux commandes au lieu d'une)",{"type":30,"tag":225,"props":1602,"children":1604},{"cta":227,"href":228,"title":1603,"type":230},"Votre système distribué tombe en cascade lors des incidents et vous ne savez pas par où commencer pour le renforcer ?",[1605],{"type":30,"tag":38,"props":1606,"children":1607},{},[1608],{"type":36,"value":1609},"L'implémentation des patterns de résilience nécessite un audit des points de défaillance critiques et un plan de priorisation. Je l'ai fait pour des équipes dans la finance, l'assurance et le e-commerce. En 30 minutes, on peut identifier les 3 flux les plus à risque dans votre architecture et définir le plan d'implémentation.",{"type":30,"tag":67,"props":1611,"children":1612},{},[],{"type":30,"tag":71,"props":1614,"children":1616},{"id":1615},"pattern-3-circuit-breaker",[1617],{"type":36,"value":1618},"Pattern 3 : Circuit Breaker",{"type":30,"tag":38,"props":1620,"children":1621},{},[1622],{"type":36,"value":1623},"Le circuit breaker est le pattern le plus important pour prévenir les cascade failures. Son principe est emprunté à l'électricité : quand un circuit est en surcharge, le disjoncteur coupe le courant pour protéger le reste du circuit.",{"type":30,"tag":38,"props":1625,"children":1626},{},[1627],{"type":30,"tag":44,"props":1628,"children":1629},{},[1630],{"type":36,"value":1631},"Les 3 états :",{"type":30,"tag":38,"props":1633,"children":1634},{},[1635,1640],{"type":30,"tag":44,"props":1636,"children":1637},{},[1638],{"type":36,"value":1639},"Closed (normal)",{"type":36,"value":1641}," : les appels passent normalement. Le circuit breaker monitore le taux d'échec.",{"type":30,"tag":38,"props":1643,"children":1644},{},[1645,1650],{"type":30,"tag":44,"props":1646,"children":1647},{},[1648],{"type":36,"value":1649},"Open",{"type":36,"value":1651}," : le taux d'échec a dépassé le seuil (par exemple, plus de 50% d'échecs sur les 10 derniers appels). Les appels échouent immédiatement sans atteindre le service défaillant. Cela protège le service défaillant de la surcharge et protège l'appelant d'une accumulation de threads.",{"type":30,"tag":38,"props":1653,"children":1654},{},[1655,1660],{"type":30,"tag":44,"props":1656,"children":1657},{},[1658],{"type":36,"value":1659},"Half-Open",{"type":36,"value":1661}," : après un délai (30 secondes par exemple), le circuit breaker laisse passer quelques appels de test. Si ils réussissent, retour à Closed. Sinon, retour à Open.",{"type":30,"tag":185,"props":1663,"children":1665},{"className":948,"code":1664,"language":950,"meta":8,"style":8},"// Exemple avec Resilience4j (Java)\nCircuitBreakerConfig config = CircuitBreakerConfig.custom()\n    .failureRateThreshold(50)\n    .waitDurationInOpenState(Duration.ofSeconds(30))\n    .slidingWindowSize(10)\n    .build();\n\nCircuitBreaker circuitBreaker = CircuitBreaker.of(\"paymentService\", config);\n\nSupplier\u003CPayment> decoratedCall = CircuitBreaker\n    .decorateSupplier(circuitBreaker, () -> paymentService.processPayment(request));\n",[1666],{"type":30,"tag":98,"props":1667,"children":1668},{"__ignoreMap":8},[1669,1677,1712,1737,1781,1806,1821,1828,1883,1890,1927],{"type":30,"tag":439,"props":1670,"children":1671},{"class":441,"line":442},[1672],{"type":30,"tag":439,"props":1673,"children":1674},{"style":446},[1675],{"type":36,"value":1676},"// Exemple avec Resilience4j (Java)\n",{"type":30,"tag":439,"props":1678,"children":1679},{"class":441,"line":452},[1680,1685,1690,1694,1699,1703,1708],{"type":30,"tag":439,"props":1681,"children":1682},{"style":968},[1683],{"type":36,"value":1684},"CircuitBreakerConfig",{"type":30,"tag":439,"props":1686,"children":1687},{"style":462},[1688],{"type":36,"value":1689}," config ",{"type":30,"tag":439,"props":1691,"children":1692},{"style":487},[1693],{"type":36,"value":981},{"type":30,"tag":439,"props":1695,"children":1696},{"style":462},[1697],{"type":36,"value":1698}," CircuitBreakerConfig",{"type":30,"tag":439,"props":1700,"children":1701},{"style":994},[1702],{"type":36,"value":997},{"type":30,"tag":439,"props":1704,"children":1705},{"style":1000},[1706],{"type":36,"value":1707},"custom",{"type":30,"tag":439,"props":1709,"children":1710},{"style":994},[1711],{"type":36,"value":1008},{"type":30,"tag":439,"props":1713,"children":1714},{"class":441,"line":478},[1715,1719,1724,1728,1733],{"type":30,"tag":439,"props":1716,"children":1717},{"style":994},[1718],{"type":36,"value":1016},{"type":30,"tag":439,"props":1720,"children":1721},{"style":1000},[1722],{"type":36,"value":1723},"failureRateThreshold",{"type":30,"tag":439,"props":1725,"children":1726},{"style":994},[1727],{"type":36,"value":1026},{"type":30,"tag":439,"props":1729,"children":1730},{"style":1029},[1731],{"type":36,"value":1732},"50",{"type":30,"tag":439,"props":1734,"children":1735},{"style":994},[1736],{"type":36,"value":1579},{"type":30,"tag":439,"props":1738,"children":1739},{"class":441,"line":508},[1740,1744,1749,1753,1758,1762,1767,1771,1776],{"type":30,"tag":439,"props":1741,"children":1742},{"style":994},[1743],{"type":36,"value":1016},{"type":30,"tag":439,"props":1745,"children":1746},{"style":1000},[1747],{"type":36,"value":1748},"waitDurationInOpenState",{"type":30,"tag":439,"props":1750,"children":1751},{"style":994},[1752],{"type":36,"value":1026},{"type":30,"tag":439,"props":1754,"children":1755},{"style":462},[1756],{"type":36,"value":1757},"Duration",{"type":30,"tag":439,"props":1759,"children":1760},{"style":994},[1761],{"type":36,"value":997},{"type":30,"tag":439,"props":1763,"children":1764},{"style":1000},[1765],{"type":36,"value":1766},"ofSeconds",{"type":30,"tag":439,"props":1768,"children":1769},{"style":994},[1770],{"type":36,"value":1026},{"type":30,"tag":439,"props":1772,"children":1773},{"style":1029},[1774],{"type":36,"value":1775},"30",{"type":30,"tag":439,"props":1777,"children":1778},{"style":994},[1779],{"type":36,"value":1780},"))\n",{"type":30,"tag":439,"props":1782,"children":1783},{"class":441,"line":517},[1784,1788,1793,1797,1802],{"type":30,"tag":439,"props":1785,"children":1786},{"style":994},[1787],{"type":36,"value":1016},{"type":30,"tag":439,"props":1789,"children":1790},{"style":1000},[1791],{"type":36,"value":1792},"slidingWindowSize",{"type":30,"tag":439,"props":1794,"children":1795},{"style":994},[1796],{"type":36,"value":1026},{"type":30,"tag":439,"props":1798,"children":1799},{"style":1029},[1800],{"type":36,"value":1801},"10",{"type":30,"tag":439,"props":1803,"children":1804},{"style":994},[1805],{"type":36,"value":1579},{"type":30,"tag":439,"props":1807,"children":1808},{"class":441,"line":526},[1809,1813,1817],{"type":30,"tag":439,"props":1810,"children":1811},{"style":994},[1812],{"type":36,"value":1016},{"type":30,"tag":439,"props":1814,"children":1815},{"style":1000},[1816],{"type":36,"value":1164},{"type":30,"tag":439,"props":1818,"children":1819},{"style":994},[1820],{"type":36,"value":1169},{"type":30,"tag":439,"props":1822,"children":1823},{"class":441,"line":547},[1824],{"type":30,"tag":439,"props":1825,"children":1826},{"emptyLinePlaceholder":13},[1827],{"type":36,"value":514},{"type":30,"tag":439,"props":1829,"children":1830},{"class":441,"line":1379},[1831,1836,1841,1845,1850,1854,1859,1863,1869,1873,1878],{"type":30,"tag":439,"props":1832,"children":1833},{"style":968},[1834],{"type":36,"value":1835},"CircuitBreaker",{"type":30,"tag":439,"props":1837,"children":1838},{"style":462},[1839],{"type":36,"value":1840}," circuitBreaker ",{"type":30,"tag":439,"props":1842,"children":1843},{"style":487},[1844],{"type":36,"value":981},{"type":30,"tag":439,"props":1846,"children":1847},{"style":462},[1848],{"type":36,"value":1849}," CircuitBreaker",{"type":30,"tag":439,"props":1851,"children":1852},{"style":994},[1853],{"type":36,"value":997},{"type":30,"tag":439,"props":1855,"children":1856},{"style":1000},[1857],{"type":36,"value":1858},"of",{"type":30,"tag":439,"props":1860,"children":1861},{"style":994},[1862],{"type":36,"value":1026},{"type":30,"tag":439,"props":1864,"children":1866},{"style":1865},"--shiki-default:#A6D189;--shiki-dark:#9ECBFF",[1867],{"type":36,"value":1868},"\"paymentService\"",{"type":30,"tag":439,"props":1870,"children":1871},{"style":994},[1872],{"type":36,"value":1037},{"type":30,"tag":439,"props":1874,"children":1875},{"style":462},[1876],{"type":36,"value":1877}," config",{"type":30,"tag":439,"props":1879,"children":1880},{"style":994},[1881],{"type":36,"value":1882},");\n",{"type":30,"tag":439,"props":1884,"children":1885},{"class":441,"line":1407},[1886],{"type":30,"tag":439,"props":1887,"children":1888},{"emptyLinePlaceholder":13},[1889],{"type":36,"value":514},{"type":30,"tag":439,"props":1891,"children":1892},{"class":441,"line":1444},[1893,1898,1903,1908,1913,1918,1922],{"type":30,"tag":439,"props":1894,"children":1895},{"style":968},[1896],{"type":36,"value":1897},"Supplier",{"type":30,"tag":439,"props":1899,"children":1900},{"style":994},[1901],{"type":36,"value":1902},"\u003C",{"type":30,"tag":439,"props":1904,"children":1905},{"style":456},[1906],{"type":36,"value":1907},"Payment",{"type":30,"tag":439,"props":1909,"children":1910},{"style":994},[1911],{"type":36,"value":1912},">",{"type":30,"tag":439,"props":1914,"children":1915},{"style":462},[1916],{"type":36,"value":1917}," decoratedCall ",{"type":30,"tag":439,"props":1919,"children":1920},{"style":487},[1921],{"type":36,"value":981},{"type":30,"tag":439,"props":1923,"children":1924},{"style":968},[1925],{"type":36,"value":1926}," CircuitBreaker\n",{"type":30,"tag":439,"props":1928,"children":1929},{"class":441,"line":1458},[1930,1934,1939,1943,1948,1952,1957,1962,1967,1971,1976,1980,1985],{"type":30,"tag":439,"props":1931,"children":1932},{"style":994},[1933],{"type":36,"value":1016},{"type":30,"tag":439,"props":1935,"children":1936},{"style":1000},[1937],{"type":36,"value":1938},"decorateSupplier",{"type":30,"tag":439,"props":1940,"children":1941},{"style":994},[1942],{"type":36,"value":1026},{"type":30,"tag":439,"props":1944,"children":1945},{"style":462},[1946],{"type":36,"value":1947},"circuitBreaker",{"type":30,"tag":439,"props":1949,"children":1950},{"style":994},[1951],{"type":36,"value":1037},{"type":30,"tag":439,"props":1953,"children":1954},{"style":994},[1955],{"type":36,"value":1956}," ()",{"type":30,"tag":439,"props":1958,"children":1959},{"style":456},[1960],{"type":36,"value":1961}," ->",{"type":30,"tag":439,"props":1963,"children":1964},{"style":462},[1965],{"type":36,"value":1966}," paymentService",{"type":30,"tag":439,"props":1968,"children":1969},{"style":994},[1970],{"type":36,"value":997},{"type":30,"tag":439,"props":1972,"children":1973},{"style":1000},[1974],{"type":36,"value":1975},"processPayment",{"type":30,"tag":439,"props":1977,"children":1978},{"style":994},[1979],{"type":36,"value":1026},{"type":30,"tag":439,"props":1981,"children":1982},{"style":462},[1983],{"type":36,"value":1984},"request",{"type":30,"tag":439,"props":1986,"children":1987},{"style":994},[1988],{"type":36,"value":1989},"));\n",{"type":30,"tag":185,"props":1991,"children":1995},{"className":1992,"code":1993,"language":1994,"meta":8,"style":8},"language-javascript shiki shiki-themes catppuccin-frappe github-dark","// Exemple avec opossum (Node.js)\nconst CircuitBreaker = require('opossum');\n\nconst breaker = new CircuitBreaker(paymentService.processPayment, {\n    timeout: 3000,\n    errorThresholdPercentage: 50,\n    resetTimeout: 30000\n});\n\nbreaker.fallback(() => ({ status: 'payment_service_unavailable' }));\n","javascript",[1996],{"type":30,"tag":98,"props":1997,"children":1998},{"__ignoreMap":8},[1999,2007,2048,2055,2103,2126,2147,2164,2180,2187],{"type":30,"tag":439,"props":2000,"children":2001},{"class":441,"line":442},[2002],{"type":30,"tag":439,"props":2003,"children":2004},{"style":446},[2005],{"type":36,"value":2006},"// Exemple avec opossum (Node.js)\n",{"type":30,"tag":439,"props":2008,"children":2009},{"class":441,"line":452},[2010,2015,2020,2025,2030,2034,2039,2043],{"type":30,"tag":439,"props":2011,"children":2012},{"style":456},[2013],{"type":36,"value":2014},"const",{"type":30,"tag":439,"props":2016,"children":2018},{"style":2017},"--shiki-default:#C6D0F5;--shiki-dark:#79B8FF",[2019],{"type":36,"value":1849},{"type":30,"tag":439,"props":2021,"children":2022},{"style":487},[2023],{"type":36,"value":2024}," =",{"type":30,"tag":439,"props":2026,"children":2027},{"style":1000},[2028],{"type":36,"value":2029}," require",{"type":30,"tag":439,"props":2031,"children":2032},{"style":462},[2033],{"type":36,"value":1026},{"type":30,"tag":439,"props":2035,"children":2036},{"style":1865},[2037],{"type":36,"value":2038},"'opossum'",{"type":30,"tag":439,"props":2040,"children":2041},{"style":462},[2042],{"type":36,"value":1056},{"type":30,"tag":439,"props":2044,"children":2045},{"style":994},[2046],{"type":36,"value":2047},";\n",{"type":30,"tag":439,"props":2049,"children":2050},{"class":441,"line":478},[2051],{"type":30,"tag":439,"props":2052,"children":2053},{"emptyLinePlaceholder":13},[2054],{"type":36,"value":514},{"type":30,"tag":439,"props":2056,"children":2057},{"class":441,"line":508},[2058,2062,2067,2071,2076,2080,2085,2090,2094,2098],{"type":30,"tag":439,"props":2059,"children":2060},{"style":456},[2061],{"type":36,"value":2014},{"type":30,"tag":439,"props":2063,"children":2064},{"style":2017},[2065],{"type":36,"value":2066}," breaker",{"type":30,"tag":439,"props":2068,"children":2069},{"style":487},[2070],{"type":36,"value":2024},{"type":30,"tag":439,"props":2072,"children":2074},{"style":2073},"--shiki-default:#CA9EE6;--shiki-default-font-weight:bold;--shiki-dark:#F97583;--shiki-dark-font-weight:inherit",[2075],{"type":36,"value":986},{"type":30,"tag":439,"props":2077,"children":2078},{"style":1000},[2079],{"type":36,"value":1849},{"type":30,"tag":439,"props":2081,"children":2082},{"style":462},[2083],{"type":36,"value":2084},"(paymentService",{"type":30,"tag":439,"props":2086,"children":2088},{"style":2087},"--shiki-default:#81C8BE;--shiki-dark:#E1E4E8",[2089],{"type":36,"value":997},{"type":30,"tag":439,"props":2091,"children":2092},{"style":462},[2093],{"type":36,"value":1975},{"type":30,"tag":439,"props":2095,"children":2096},{"style":994},[2097],{"type":36,"value":1037},{"type":30,"tag":439,"props":2099,"children":2100},{"style":994},[2101],{"type":36,"value":2102}," {\n",{"type":30,"tag":439,"props":2104,"children":2105},{"class":441,"line":517},[2106,2111,2116,2121],{"type":30,"tag":439,"props":2107,"children":2108},{"style":462},[2109],{"type":36,"value":2110},"    timeout",{"type":30,"tag":439,"props":2112,"children":2113},{"style":2087},[2114],{"type":36,"value":2115},":",{"type":30,"tag":439,"props":2117,"children":2118},{"style":1029},[2119],{"type":36,"value":2120}," 3000",{"type":30,"tag":439,"props":2122,"children":2123},{"style":994},[2124],{"type":36,"value":2125},",\n",{"type":30,"tag":439,"props":2127,"children":2128},{"class":441,"line":526},[2129,2134,2138,2143],{"type":30,"tag":439,"props":2130,"children":2131},{"style":462},[2132],{"type":36,"value":2133},"    errorThresholdPercentage",{"type":30,"tag":439,"props":2135,"children":2136},{"style":2087},[2137],{"type":36,"value":2115},{"type":30,"tag":439,"props":2139,"children":2140},{"style":1029},[2141],{"type":36,"value":2142}," 50",{"type":30,"tag":439,"props":2144,"children":2145},{"style":994},[2146],{"type":36,"value":2125},{"type":30,"tag":439,"props":2148,"children":2149},{"class":441,"line":547},[2150,2155,2159],{"type":30,"tag":439,"props":2151,"children":2152},{"style":462},[2153],{"type":36,"value":2154},"    resetTimeout",{"type":30,"tag":439,"props":2156,"children":2157},{"style":2087},[2158],{"type":36,"value":2115},{"type":30,"tag":439,"props":2160,"children":2161},{"style":1029},[2162],{"type":36,"value":2163}," 30000\n",{"type":30,"tag":439,"props":2165,"children":2166},{"class":441,"line":1379},[2167,2172,2176],{"type":30,"tag":439,"props":2168,"children":2169},{"style":994},[2170],{"type":36,"value":2171},"}",{"type":30,"tag":439,"props":2173,"children":2174},{"style":462},[2175],{"type":36,"value":1056},{"type":30,"tag":439,"props":2177,"children":2178},{"style":994},[2179],{"type":36,"value":2047},{"type":30,"tag":439,"props":2181,"children":2182},{"class":441,"line":1407},[2183],{"type":30,"tag":439,"props":2184,"children":2185},{"emptyLinePlaceholder":13},[2186],{"type":36,"value":514},{"type":30,"tag":439,"props":2188,"children":2189},{"class":441,"line":1444},[2190,2195,2199,2204,2208,2213,2218,2222,2227,2232,2236,2241,2246,2251],{"type":30,"tag":439,"props":2191,"children":2192},{"style":462},[2193],{"type":36,"value":2194},"breaker",{"type":30,"tag":439,"props":2196,"children":2197},{"style":2087},[2198],{"type":36,"value":997},{"type":30,"tag":439,"props":2200,"children":2201},{"style":1000},[2202],{"type":36,"value":2203},"fallback",{"type":30,"tag":439,"props":2205,"children":2206},{"style":462},[2207],{"type":36,"value":1026},{"type":30,"tag":439,"props":2209,"children":2210},{"style":994},[2211],{"type":36,"value":2212},"()",{"type":30,"tag":439,"props":2214,"children":2215},{"style":456},[2216],{"type":36,"value":2217}," =>",{"type":30,"tag":439,"props":2219,"children":2220},{"style":462},[2221],{"type":36,"value":1483},{"type":30,"tag":439,"props":2223,"children":2224},{"style":994},[2225],{"type":36,"value":2226},"{",{"type":30,"tag":439,"props":2228,"children":2229},{"style":462},[2230],{"type":36,"value":2231}," status",{"type":30,"tag":439,"props":2233,"children":2234},{"style":2087},[2235],{"type":36,"value":2115},{"type":30,"tag":439,"props":2237,"children":2238},{"style":1865},[2239],{"type":36,"value":2240}," 'payment_service_unavailable'",{"type":30,"tag":439,"props":2242,"children":2243},{"style":994},[2244],{"type":36,"value":2245}," }",{"type":30,"tag":439,"props":2247,"children":2248},{"style":462},[2249],{"type":36,"value":2250},"))",{"type":30,"tag":439,"props":2252,"children":2253},{"style":994},[2254],{"type":36,"value":2047},{"type":30,"tag":67,"props":2256,"children":2257},{},[],{"type":30,"tag":71,"props":2259,"children":2261},{"id":2260},"les-compléments-bulkhead-et-fallback",[2262],{"type":36,"value":2263},"Les compléments : bulkhead et fallback",{"type":30,"tag":38,"props":2265,"children":2266},{},[2267,2272],{"type":30,"tag":44,"props":2268,"children":2269},{},[2270],{"type":36,"value":2271},"Bulkhead :",{"type":36,"value":2273}," isoler les ressources par service externe. Chaque service externe a son propre pool de threads ou de connexions : une dégradation d'un service ne consomme pas toutes les ressources de l'appelant.",{"type":30,"tag":38,"props":2275,"children":2276},{},[2277,2282],{"type":30,"tag":44,"props":2278,"children":2279},{},[2280],{"type":36,"value":2281},"Fallback :",{"type":36,"value":2283}," définir un comportement de repli quand le circuit est ouvert. Pas \"retourner une erreur 500\", mais retourner un résultat dégradé acceptable.",{"type":30,"tag":620,"props":2285,"children":2286},{},[2287,2292,2297],{"type":30,"tag":624,"props":2288,"children":2289},{},[2290],{"type":36,"value":2291},"Service de recommandations indisponible → retourner des recommandations statiques ou populaires",{"type":30,"tag":624,"props":2293,"children":2294},{},[2295],{"type":36,"value":2296},"Service de notation indisponible → afficher la note moyenne sans recalcul temps-réel",{"type":30,"tag":624,"props":2298,"children":2299},{},[2300],{"type":36,"value":2301},"Service de paiement indisponible → mettre la commande en queue pour traitement différé",{"type":30,"tag":38,"props":2303,"children":2304},{},[2305],{"type":36,"value":2306},"Votre système doit fonctionner de façon dégradée quand un service non-critique est indisponible. Il ne doit pas être entièrement indisponible.",{"type":30,"tag":67,"props":2308,"children":2309},{},[],{"type":30,"tag":71,"props":2311,"children":2313},{"id":2312},"ordre-dimplémentation",[2314],{"type":36,"value":2315},"Ordre d'implémentation",{"type":30,"tag":2317,"props":2318,"children":2319},"ol",{},[2320,2330,2340],{"type":30,"tag":624,"props":2321,"children":2322},{},[2323,2328],{"type":30,"tag":44,"props":2324,"children":2325},{},[2326],{"type":36,"value":2327},"Timeout d'abord",{"type":36,"value":2329}," (1 journée) : ajouter des timeouts explicites sur tous les appels vers des services externes. C'est la correction la plus rapide et la plus impactante.",{"type":30,"tag":624,"props":2331,"children":2332},{},[2333,2338],{"type":30,"tag":44,"props":2334,"children":2335},{},[2336],{"type":36,"value":2337},"Retry sur les erreurs transientes",{"type":36,"value":2339}," (2 à 3 jours) : identifier les erreurs transientes dans votre système et ajouter un retry avec backoff exponentiel. S'assurer que les opérations retriées sont idempotentes.",{"type":30,"tag":624,"props":2341,"children":2342},{},[2343,2348],{"type":30,"tag":44,"props":2344,"children":2345},{},[2346],{"type":36,"value":2347},"Circuit breaker sur les services critiques",{"type":36,"value":2349}," (1 semaine) : identifier les 5 à 10 dépendances externes les plus critiques et implémenter le circuit breaker avec monitoring.",{"type":30,"tag":38,"props":2351,"children":2352},{},[2353],{"type":36,"value":2354},"En moins de 2 semaines, votre système est significativement plus résilient.",{"type":30,"tag":67,"props":2356,"children":2357},{},[],{"type":30,"tag":71,"props":2359,"children":2361},{"id":2360},"faq-sur-les-patterns-de-résilience",[2362],{"type":36,"value":2363},"FAQ sur les patterns de résilience",{"type":30,"tag":714,"props":2365,"children":2366},{},[2367,2372],{"type":30,"tag":718,"props":2368,"children":2369},{},[2370],{"type":36,"value":2371},"1. Les patterns de résilience s'appliquent-ils aux monolithes ou seulement aux microservices ?",{"type":30,"tag":38,"props":2373,"children":2374},{},[2375,2377,2382],{"type":36,"value":2376},"Aux deux. Tout système qui appelle des services externes (base de données, cache, API tierce, service d'email) bénéficie des timeouts, retries, et circuit breakers. Dans un monolithe, les patterns s'appliquent sur les appels vers les dépendances externes. Dans les ",{"type":30,"tag":142,"props":2378,"children":2379},{"href":5},[2380],{"type":36,"value":2381},"microservices avec une base de données par service",{"type":36,"value":2383},", ils s'appliquent aussi aux appels inter-services, et sont même indispensables pour gérer la cohérence éventuelle entre services. J'ai implémenté ces patterns dans des monolithes bancaires aussi bien que dans des architectures microservices de e-commerce.",{"type":30,"tag":714,"props":2385,"children":2386},{},[2387,2392],{"type":30,"tag":718,"props":2388,"children":2389},{},[2390],{"type":36,"value":2391},"2. Quel outil choisir pour implémenter les patterns de résilience ?",{"type":30,"tag":38,"props":2393,"children":2394},{},[2395],{"type":36,"value":2396},"Par écosystème : Java/Kotlin → Resilience4j (successeur de Hystrix, maintenu activement). Node.js → opossum. Python → tenacity pour le retry. Go → gobreaker. Spring Boot → intégration native de Resilience4j via Spring Cloud Circuit Breaker. À l'infrastructure : Istio et Envoy permettent d'implémenter ces patterns au niveau du service mesh, sans modification du code applicatif, utile pour les équipes qui gèrent de nombreux services.",{"type":30,"tag":714,"props":2398,"children":2399},{},[2400,2405],{"type":30,"tag":718,"props":2401,"children":2402},{},[2403],{"type":36,"value":2404},"3. Comment monitorer l'état des circuit breakers en production ?",{"type":30,"tag":38,"props":2406,"children":2407},{},[2408,2410,2416],{"type":36,"value":2409},"Les circuit breakers ouverts sont des alertes : ils signalent qu'un service est en difficulté. Exposer l'état des circuit breakers dans votre système de monitoring (Prometheus + Grafana, Datadog, New Relic). Configurer une alerte quand un circuit breaker passe à l'état Open : c'est un signal d'action, pas seulement d'information. Un circuit breaker qui reste ouvert en permanence indique un service en difficulté structurelle. Ces métriques de disponibilité font partie des ",{"type":30,"tag":142,"props":2411,"children":2413},{"href":2412},"/fr/management/metriques-management-developpeurs-motivation",[2414],{"type":36,"value":2415},"indicateurs clés à suivre pour les équipes engineering",{"type":36,"value":2417}," : elles objectivent l'état de santé de l'architecture et rendent visibles les progrès réalisés.",{"type":30,"tag":714,"props":2419,"children":2420},{},[2421,2426],{"type":30,"tag":718,"props":2422,"children":2423},{},[2424],{"type":36,"value":2425},"4. Comment tester les patterns de résilience sans attendre un incident en production ?",{"type":30,"tag":38,"props":2427,"children":2428},{},[2429,2431,2437],{"type":36,"value":2430},"Le chaos engineering est la méthode de référence. Outils : Chaos Monkey (Netflix), Gremlin, ou des scripts simples qui introduisent des latences artificielles en staging. Pour commencer sans outil spécifique : injecter un ",{"type":30,"tag":98,"props":2432,"children":2434},{"className":2433},[],[2435],{"type":36,"value":2436},"sleep(5000)",{"type":36,"value":2438}," dans le service cible en environnement de test et vérifier que les timeouts et circuit breakers fonctionnent comme attendu. Ce test prend 30 minutes et devrait être dans votre suite de tests de non-régression.",{"type":30,"tag":67,"props":2440,"children":2441},{},[],{"type":30,"tag":225,"props":2443,"children":2444},{"cta":785,"href":786,"title":787,"type":788},[2445],{"type":30,"tag":38,"props":2446,"children":2447},{},[2448],{"type":36,"value":2449},"L'Engineering Maturity Self-Assessment couvre le domaine Résilience & Architecture : évaluez en 10 minutes votre niveau sur les patterns de résilience, la robustesse de vos services, et la gestion des pannes. Obtenez un score et un plan d'action personnalisé.",{"type":30,"tag":796,"props":2451,"children":2452},{},[2453],{"type":36,"value":800},{"title":8,"searchDepth":452,"depth":452,"links":2455},[2456,2457,2458,2459,2460,2461,2462],{"id":864,"depth":452,"text":867},{"id":901,"depth":452,"text":904},{"id":1185,"depth":452,"text":1188},{"id":1615,"depth":452,"text":1618},{"id":2260,"depth":452,"text":2263},{"id":2312,"depth":452,"text":2315},{"id":2360,"depth":452,"text":2363},"content:fr:architecture-craft:patterns-resilience-circuit-breaker-retry.md","fr/architecture-craft/patterns-resilience-circuit-breaker-retry.md","fr/architecture-craft/patterns-resilience-circuit-breaker-retry",1775679739647]