En 2021, notre équipe a passé 4 mois à découper un monolithe Django. Deux semaines après le go-live, la latence avait triplé et les bugs de cohérence de données s'accumulaient. On a failli tout annuler. Ce guide, c'est ce que j'aurais voulu lire avant.
Pourquoi les microservices font peur (à raison)
Un monolithe Django bien structuré peut tenir des années et supporter des millions d'utilisateurs. Netflix, Airbnb, Shopify ont commencé en monolithe. Le découpage prématuré est l'une des erreurs les plus coûteuses en ingénierie logicielle.
Les vrais signaux qui justifient la migration :
- Plusieurs équipes modifient le même code et se bloquent mutuellement
- Les déploiements prennent plus de 30 minutes et impliquent tout le monde
- Certains composants ont des besoins de scaling radicalement différents
- Le build/test local prend 10+ minutes
Identifier les bounded contexts avant tout
Avant d'écrire une seule ligne de code, cartographiez vos domaines métier. Utilisez ce script pour analyser les dépendances entre apps Django :
import ast, os
from collections import defaultdict
def analyser_imports(base_dir):
dependances = defaultdict(set)
for root, _, files in os.walk(base_dir):
for f in files:
if not f.endswith('.py'):
continue
chemin = os.path.join(root, f)
app = chemin.replace(base_dir, '').split(os.sep)[1]
with open(chemin) as src:
try:
tree = ast.parse(src.read())
except SyntaxError:
continue
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module:
dependances[app].add(node.module.split('.')[0])
return dependances
Les apps avec le moins de dépendances entrantes sont vos candidats idéaux pour commencer.
Communication entre services : le choix qui détermine tout
ApprocheQuand l'utiliserPiège principal HTTP/RESTAppels synchrones simplesCouplage temporel, cascade de pannes Events (Kafka)Actions asynchrones, audit trailComplexité opérationnelle gRPCCommunication inter-services haute fréquenceDebugging difficile Ma règle : commencez par HTTP/REST + circuit breaker. Passez aux events seulement quand le couplage temporel pose des problèmes réels.
Gestion des données : la règle d'or
Chaque service doit posséder sa propre base. Partager une base entre deux services, c'est garder le couplage du monolithe en pire. Si le service A a besoin de données du service B, il les demande via API ou les réplique via events.
Authentification : JWT sans appel centralisé
# Chaque service valide le token localement
import jwt
from django.conf import settings
def verifier_token(token):
payload = jwt.decode(token, settings.JWT_PUBLIC_KEY, algorithms=["RS256"])
return payload # contient user_id, roles, expiration
Utilisez RS256 (clé publique/privée) plutôt que HS256 pour que chaque service puisse valider sans connaître le secret.
L'erreur que tout le monde fait : migrer trop vite
Le strangler fig pattern est la seule approche sûre :
- Le nouveau service et le monolithe coexistent et font la même chose
- Le trafic est redirigé progressivement (10% ? 50% ? 100%)
- Le code monolithe est supprimé seulement quand le nouveau est stable
Résistez à l'envie de "couper d'un coup". Ça prend 3x plus de temps que prévu et ça se passe toujours mal.
Ce que je ferais différemment
Extraire d'abord les services les plus périphériques (notifications, reporting), pas les plus centraux (auth, billing). Les erreurs sur les périphériques coûtent moins cher. Et instrumentez tout avant de migrer : sans métriques de référence, vous naviguez à l'aveugle.