Jour 11 Day 11 · mercredi 12 août 2026 Wednesday 12 August 2026 Architecture Intermédiaire
Microservices vs monolithe Microservices vs monolith
Savoir défendre le monolithe ET expliquer quand les microservices se justifient : la question d'architecture préférée des entretiens, où la nuance rapporte plus que le buzzword. Being able to defend the monolith AND explain when microservices earn their keep: the favorite architecture question in interviews, where nuance pays more than buzzwords.
L’essentiel
Un monolithe est une application déployée comme une seule unité : un processus, une base de données, un déploiement. Des microservices découpent le système en services indépendants, chacun avec son code, sa base et son cycle de déploiement, communiquant par le réseau.
| Monolithe | Microservices | |
|---|---|---|
| Déploiement | une unité, atomique | indépendant, service par service |
| Données | une base, transactions ACID | database-per-service, cohérence à terme |
| Appels | fonctions — gratuits, fiables | réseau — latence, pannes partielles |
| Ops | 1 pipeline, 1 monitoring | N pipelines, tracing distribué, plateforme |
| Équipe | une petite équipe suffit | exige plusieurs équipes autonomes |
| Debugging | une stack trace | une enquête multi-services |
Le point que les entretiens cherchent à vérifier : le monolithe est souvent le bon choix, surtout en début de projet. Un appel de fonction est infiniment plus simple qu’un appel réseau — toute la colonne de droite se paie cash. Le mauvais réflexe « startup = microservices » a coulé plus de projets que les monolithes qu’il prétendait éviter.
La vraie alternative au plat de spaghetti n’est pas le microservice, c’est le monolithe modulaire : un seul déployable, mais des modules internes aux frontières nettes (le module billing n’accède au module users que par son interface publique). On garde la simplicité opérationnelle, on prépare un éventuel découpage futur — et si les frontières sont bonnes, extraire un module en service devient un déménagement, pas une réécriture.
🎤 En entretien — savoir défendre le monolithe est le vrai signal de maturité. « Pour ce projet, je garderais un monolithe modulaire : une seule équipe, un domaine encore mouvant, aucun besoin de scaling asymétrique » vaut plus que n’importe quel buzzword Kubernetes.
Comment ça marche
Ce que les microservices apportent vraiment — trois promesses, toutes organisationnelles autant que techniques :
- Déploiement indépendant : l’équipe paiement déploie 10 fois par jour sans attendre le train de release des autres. C’est LA promesse centrale — si vos services doivent se déployer ensemble, vous n’avez pas des microservices.
- Scaling ciblé : on réplique le service de recherche sous forte charge sans dupliquer tout le reste. (Honnêteté : un monolithe se réplique aussi très bien derrière un load balancer — l’argument vaut surtout pour des besoins très asymétriques : GPU, mémoire, langage spécifique.)
- Ownership d’équipe : chaque équipe possède ses services de bout en bout — code, base, astreinte. C’est la loi de Conway appliquée volontairement : l’architecture reflète l’organisation, autant la choisir. Corollaire : découper en microservices une équipe de 3 devs, c’est créer des frontières entre… personne.
💡 Le test décisif — une seule question juge une architecture microservices : « peux-tu déployer ce service seul, sans coordonner personne ? ». Si la réponse est non, vous payez le prix du distribué sans son bénéfice central.
Les coûts cachés — tout ce qu’un appel de fonction faisait gratuitement :
- Le réseau : latence, timeouts, retries (avec idempotence !), pannes partielles, circuit breakers. Un appel qui ne pouvait pas échouer devient un appel qui échoue à 2h du matin.
- La cohérence des données : chaque service a sa base (database-per-service — sinon le couplage par le schéma ruine l’indépendance). Conséquence : plus de transaction ACID entre services ni de JOIN SQL cross-domaines. On vit avec la cohérence à terme (eventual consistency), et une commande qui touche stock + paiement + livraison devient une saga : une séquence de transactions locales, où chaque échec déclenche des transactions de compensation qui défont les étapes précédentes. En deux phrases en entretien, ça suffit — savoir que le problème existe compte plus que les détails.
- L’observabilité : une requête traverse 6 services ; sans tracing distribué (correlation ID propagé, OpenTelemetry) et logs centralisés, chaque bug est une enquête.
- L’ops : N pipelines CI/CD, N services à monitorer, la gestion des versions d’API entre services. Il faut une plateforme (Kubernetes ou équivalent) et une équipe capable de l’opérer.
Communication : synchrone (REST, gRPC) — simple à raisonner, mais couplage temporel : si le service aval est lent ou down, l’amont l’est aussi, et les pannes se propagent en cascade. Asynchrone (événements via un broker : Kafka, RabbitMQ) — le producteur publie « OrderCreated » et n’attend personne ; découplage et absorption des pics, au prix de la cohérence à terme et d’un debugging plus difficile. Une API gateway sert de point d’entrée unique aux clients : routing, authentification, rate limiting, agrégation — les clients n’ont pas à connaître la topologie interne.
Concepts clés à maîtriser
- Monolithe modulaire : la réponse nuancée qui fait mouche en entretien. Frontières logiques sans frontières réseau.
- Distributed monolith : l’anti-pattern n°1 — des services séparés par le réseau mais couplés au point de devoir se déployer ensemble. Tous les coûts du distribué, aucun bénéfice (voir l’encadré des pièges).
- Database-per-service : condition nécessaire de l’indépendance. Deux services qui partagent une base sont couplés par le schéma — un
ALTER TABLEde l’un casse l’autre. - Saga : la réponse aux transactions distribuées — transactions locales + compensations, orchestrées (un coordinateur) ou chorégraphiées (chaîne d’événements).
- Strangler fig : la stratégie de migration raisonnable — on extrait du monolithe une capacité à la fois, un proxy route progressivement le trafic vers le nouveau service, le monolithe « s’étrangle » petit à petit. Jamais de big bang rewrite.
┌───────┐
Clients ──▶ │ Proxy │ route de plus en plus
└───┬───┘ vers les services extraits
┌────────┴────────┐
▼ ▼
┌────────────┐ ┌──────────────┐
│ Monolithe │ │ Service │
│ (rétrécit) │ │ extrait n° 1 │
└────────────┘ └──────────────┘
/orders /users /billing
- Quand migrer : quand les limites deviennent concrètes — des équipes qui se bloquent mutuellement au déploiement, un module aux besoins de scaling radicalement différents, une organisation qui dépasse ce qu’un déployable unique supporte. La douleur d’abord, le découpage ensuite.
En entretien
« Monolithe ou microservices pour une startup qui démarre ? » — Monolithe, modulaire de préférence. À ce stade, la vitesse d’itération prime et le produit pivote ; les microservices figent des frontières qu’on ne connaît pas encore, et imposent des coûts (réseau, ops, cohérence) sans équipe pour les absorber. Citer le « MonolithFirst » de Fowler : les microservices réussis sont presque tous des monolithes découpés après coup.
« C’est quoi un distributed monolith ? » — Des services séparés par le réseau mais toujours couplés : déploiements coordonnés, base partagée, chaînes d’appels synchrones. Le pire des deux mondes : la latence et les pannes partielles du distribué, sans le déploiement indépendant. Causes typiques : découpage par couches techniques plutôt que par domaines métier, et frontières tracées trop tôt.
« Comment gérer une transaction qui traverse plusieurs services ? » — On ne peut plus avoir d’ACID global ; le pattern saga découpe l’opération en transactions locales, chacune avec une compensation en cas d’échec en aval (annuler la réservation, rembourser le paiement). Ajouter que ça se conçoit : opérations idempotentes, états intermédiaires visibles (« paiement en attente »).
« Communication synchrone ou asynchrone entre services ? » — Synchrone (REST/gRPC) quand on a besoin de la réponse immédiatement ; mais chaque appel synchrone propage les pannes et additionne les latences. Asynchrone (événements) pour tout ce qui peut l’être : découplage, résilience aux pics, mais cohérence à terme. Règle pratique : synchrone pour les queries client, asynchrone entre services quand c’est possible.
« Comment migrer un monolithe vers des microservices ? » — Strangler fig : d’abord modulariser le monolithe pour révéler les vraies frontières, puis extraire la capacité qui a le meilleur ratio douleur/risque (souvent un domaine périphérique), router le trafic via un proxy ou une gateway, répéter. Chaque extraction doit se justifier seule — si aucune ne se justifie, on garde le monolithe et c’est très bien.
Pièges & idées reçues
⚠️ Le distributed monolith vous guette — le symptôme infaillible : « on déploie les trois services ensemble le jeudi ». Base partagée, API fragiles, chaînes d’appels synchrones : vous payez la latence et les pannes partielles du distribué sans son seul vrai bénéfice, le déploiement indépendant.
- « Les microservices, c’est plus scalable » — un monolithe répliqué derrière un load balancer scale très bien. Le scaling ciblé ne se justifie que pour des besoins vraiment asymétriques.
- Microservices à 3 devs : les frontières de services servent à découpler des équipes. Sans équipes multiples, on hérite des coûts sans les bénéfices.
- Base partagée entre services : le couplage par le schéma annule le déploiement indépendant — c’est le chemin le plus court vers le distributed monolith.
- Ignorer le réseau : traiter un appel inter-service comme un appel de fonction (pas de timeout, pas de retry, pas d’idempotence), c’est découvrir les 8 fallacies of distributed computing en production.
- Découper trop tôt : les frontières de domaines n’apparaissent qu’avec l’usage. Un mauvais découpage en microservices se corrige beaucoup plus cher qu’un mauvais découpage en modules.
- Migrer par mode : « Netflix le fait » — Netflix a des milliers d’ingénieurs. La bonne question n’est jamais « comment font les GAFAM » mais « quel problème concret ai-je aujourd’hui ».
Pour aller plus loin
- Martin Fowler — Microservices et MonolithFirst
- microservices.io : le catalogue de patterns de Chris Richardson, notamment Saga et Database per service
- Strangler Fig Application : la stratégie de migration
- Exercice de pensée utile en entretien : prendre un de vos projets et argumenter contre son découpage en microservices — l’exercice inverse du réflexe habituel
The essentials
A monolith is an application deployed as a single unit: one process, one database, one deployment. Microservices split the system into independent services, each with its own code, database and deployment cycle, communicating over the network.
| Monolith | Microservices | |
|---|---|---|
| Deployment | one unit, atomic | independent, service by service |
| Data | one database, ACID transactions | database-per-service, eventual consistency |
| Calls | function calls — free, reliable | network — latency, partial failures |
| Ops | 1 pipeline, 1 monitoring setup | N pipelines, distributed tracing, a platform |
| Team | one small team is enough | requires several autonomous teams |
| Debugging | one stack trace | a multi-service investigation |
The point interviews try to verify: the monolith is often the right choice, especially early in a project. A function call is infinitely simpler than a network call — the whole right-hand column comes at full price. The knee-jerk “startup = microservices” has sunk more projects than the monoliths it claimed to avoid.
The real alternative to spaghetti is not microservices, it’s the modular monolith: one deployable, but internal modules with clean boundaries (the billing module only touches the users module through its public interface). You keep the operational simplicity and prepare a possible future split — and if the boundaries are good, extracting a module into a service becomes a move, not a rewrite.
🎤 In an interview — being able to defend the monolith is the real maturity signal. “For this project I’d keep a modular monolith: one team, a still-moving domain, no asymmetric scaling need” is worth more than any Kubernetes buzzword.
How it works
What microservices actually deliver — three promises, all as organizational as they are technical:
- Independent deployment: the payments team deploys 10 times a day without waiting for anyone’s release train. This is THE central promise — if your services must deploy together, you don’t have microservices.
- Targeted scaling: you replicate the search service under heavy load without duplicating everything else. (Honesty: a monolith also replicates just fine behind a load balancer — the argument mostly holds for very asymmetric needs: GPU, memory, a specific language.)
- Team ownership: each team owns its services end to end — code, database, on-call. That’s Conway’s law applied deliberately: architecture mirrors the organization, so choose it. Corollary: splitting a 3-developer team into microservices means drawing boundaries between… nobody.
💡 The decisive test — a single question judges a microservices architecture: “can you deploy this service alone, without coordinating with anyone?”. If the answer is no, you’re paying the price of distribution without its central benefit.
The hidden costs — everything a function call used to do for free:
- The network: latency, timeouts, retries (with idempotency!), partial failures, circuit breakers. A call that could not fail becomes a call that fails at 2am.
- Data consistency: each service owns its database (database-per-service — otherwise schema coupling ruins the independence). Consequence: no more ACID transactions across services, no cross-domain SQL JOINs. You live with eventual consistency, and an order touching stock + payment + shipping becomes a saga: a sequence of local transactions where any failure triggers compensating transactions that undo the previous steps. Two sentences in an interview are enough — knowing the problem exists matters more than the details.
- Observability: a request crosses 6 services; without distributed tracing (a propagated correlation ID, OpenTelemetry) and centralized logs, every bug is a detective case.
- Ops: N CI/CD pipelines, N services to monitor, API versioning between services. You need a platform (Kubernetes or equivalent) and a team able to operate it.
Communication: synchronous (REST, gRPC) — easy to reason about, but temporally coupled: if the downstream service is slow or down, so is the upstream one, and failures cascade. Asynchronous (events through a broker: Kafka, RabbitMQ) — the producer publishes “OrderCreated” and waits for no one; decoupling and burst absorption, at the price of eventual consistency and harder debugging. An API gateway acts as the single entry point for clients: routing, authentication, rate limiting, aggregation — clients never need to know the internal topology.
Key concepts to master
- Modular monolith: the nuanced answer that lands in interviews. Logical boundaries without network boundaries.
- Distributed monolith: the number one anti-pattern — services separated by the network yet so coupled they must deploy together. Every cost of distribution, none of the benefits (see the pitfalls callout).
- Database-per-service: a necessary condition for independence. Two services sharing a database are coupled through the schema — one service’s
ALTER TABLEbreaks the other. - Saga: the answer to distributed transactions — local transactions plus compensations, either orchestrated (a coordinator) or choreographed (a chain of events).
- Strangler fig: the sane migration strategy — extract one capability at a time from the monolith, a proxy gradually routes traffic to the new service, and the monolith gets “strangled” bit by bit. Never a big-bang rewrite.
┌───────┐
Clients ──▶ │ Proxy │ routes more and more
└───┬───┘ to the extracted services
┌────────┴────────┐
▼ ▼
┌────────────┐ ┌──────────────┐
│ Monolith │ │ Extracted │
│ (shrinking)│ │ service #1 │
└────────────┘ └──────────────┘
/orders /users /billing
- When to migrate: when the limits become concrete — teams blocking each other at deployment time, a module with radically different scaling needs, an organization outgrowing what a single deployable supports. Pain first, split second.
In an interview
“Monolith or microservices for a brand-new startup?” — Monolith, modular if possible. At that stage iteration speed rules and the product pivots; microservices freeze boundaries you don’t know yet, and impose costs (network, ops, consistency) with no team to absorb them. Cite Fowler’s “MonolithFirst”: nearly every successful microservices system started as a monolith that got split later.
“What is a distributed monolith?” — Services separated by the network but still coupled: coordinated deployments, shared database, chains of synchronous calls. The worst of both worlds: the latency and partial failures of distribution, without independent deployment. Typical causes: splitting by technical layers instead of business domains, and drawing boundaries too early.
“How do you handle a transaction spanning several services?” — Global ACID is gone; the saga pattern splits the operation into local transactions, each with a compensation if a later step fails (cancel the reservation, refund the payment). Add that it’s a design exercise: idempotent operations, visible intermediate states (“payment pending”).
“Synchronous or asynchronous communication between services?” — Synchronous (REST/gRPC) when you need the answer right now; but every synchronous call propagates failures and adds up latencies. Asynchronous (events) for everything that can be: decoupling, resilience to bursts, but eventual consistency. Practical rule: synchronous for client-facing queries, asynchronous between services whenever possible.
“How do you migrate a monolith to microservices?” — Strangler fig: first modularize the monolith to reveal the real boundaries, then extract the capability with the best pain-to-risk ratio (often a peripheral domain), route traffic through a proxy or gateway, repeat. Each extraction must justify itself — if none does, keep the monolith and that’s perfectly fine.
Pitfalls & misconceptions
⚠️ The distributed monolith is watching you — the infallible symptom: “we deploy the three services together on Thursdays”. Shared database, fragile APIs, chains of synchronous calls: you pay the latency and partial failures of distribution without its one real benefit, independent deployment.
- “Microservices are more scalable” — a replicated monolith behind a load balancer scales very well. Targeted scaling only pays off for genuinely asymmetric needs.
- Microservices with 3 devs: service boundaries exist to decouple teams. Without multiple teams, you inherit the costs without the benefits.
- Shared database between services: schema coupling cancels independent deployment — the shortest road to the distributed monolith.
- Ignoring the network: treating an inter-service call like a function call (no timeout, no retry, no idempotency) means discovering the 8 fallacies of distributed computing in production.
- Splitting too early: domain boundaries only reveal themselves through use. A bad microservice split costs far more to fix than a bad module split.
- Migrating by fashion: “Netflix does it” — Netflix has thousands of engineers. The right question is never “what do the FAANGs do” but “what concrete problem do I have today”.
Going further
- Martin Fowler — Microservices and MonolithFirst
- microservices.io: Chris Richardson’s pattern catalog, especially Saga and Database per service
- Strangler Fig Application: the migration strategy
- A useful thought exercise for interviews: take one of your projects and argue against splitting it into microservices — the reverse of the usual reflex