Aller au contenu
14 août 2026·8 min de lecture

Une frontière de service issue des accès aux données

Trouvez une frontière de service issue des accès aux données en mesurant les coécritures, les lectures de décision et les transactions à garder locales.

Une frontière de service issue des accès aux données

Une frontière de service est crédible quand chaque côté peut valider ses propres modifications sans demander à l'autre de participer à la même transaction. Les organigrammes, les cartes de capacités et les noms relevés pendant un atelier peuvent suggérer où chercher. La base de données révèle si la séparation proposée résistera à la production.

Je commence par les schémas d'accès aux données parce que les anciens systèmes inscrivent leurs véritables contrats dans les lectures, les écritures, les verrous, les déclencheurs, les traitements et les procédures de reprise. La difficulté consiste à distinguer un couplage accidentel d'un invariant métier. Un écran qui lit le nom du client à côté de ses factures crée une dépendance de présentation. Une routine comptable qui met à jour une facture, une écriture au grand livre et un solde de crédit dans un même commit peut protéger un invariant qui ne tolère aucun succès partiel. Ces deux dépendances ne se traitent pas de la même façon.

Le résultat utile n'est pas un joli diagramme de domaines. C'est un dossier de preuves: une carte de propriété des tables, une matrice des tables écrites dans la même transaction, une carte des lectures qui traversent les domaines envisagés et une courte liste des invariants qui expliquent les groupes les plus forts. Avec ces preuves, une équipe peut choisir une frontière et préciser tout ce qui doit changer avant le premier déploiement indépendant.

Commencer par les transactions, pas par le nom des tables

Les tables écrites dans la même transaction constituent le premier signal le plus fort, car l'application traite aujourd'hui ces modifications comme une unité de réussite ou d'échec. Si invoice, ledger_entry et customer_balance changent régulièrement sous le même identifiant de transaction, les répartir entre plusieurs services remplacerait un commit local par de la coordination, de la compensation ou une règle métier différente.

Les noms trompent. Une table appelée customer peut contenir l'identité du compte, le statut de crédit, les préférences de livraison et un total commercial dénormalisé. Une table appelée order_status peut faire office de file partagée par la préparation et la facturation. Les préfixes reflètent souvent l'équipe qui a créé une table, pas le comportement qui en dépend désormais. Même les clés étrangères décrivent seulement les relations référentielles déclarées. Elles ne disent rien du programme nocturne qui lit trois tables, en écrit deux autres et doit pouvoir reprendre après la ligne 80 000.

Définissez une transaction comme la voit la base de données: les instructions entre begin et commit ou rollback, y compris celles exécutées par les déclencheurs et les procédures stockées. Chaque instruction en autocommit forme sa propre transaction. Les traitements par lots demandent un identifiant supplémentaire pour l'exécution et le point de reprise, car une boucle qui valide tous les 500 enregistrements porte une opération métier plus large que chaque transaction de base de données.

Capturez au minimum ces champs pour chaque accès observé:

  • identifiant de transaction et horodatage
  • exécutable, traitement, route ou point d'entrée
  • table et type d'opération
  • lignes touchées ou classe approximative de cardinalité
  • chaîne d'appels ou nom de procédure stockée, si disponible

Ne commencez pas par affecter chaque table à un domaine. Constituez d'abord les faits sans les forcer à confirmer la réponse souhaitée. Les étiquettes de domaine viennent après l'apparition des groupes de coécriture. Cet ordre évite que le vocabulaire de l'atelier fausse la mesure.

Construire une matrice de coécriture qui expose le travail atomique

Une matrice de coécriture compte le nombre de fois où deux tables reçoivent des écritures dans la même transaction de base de données. Elle transforme des milliers de traces en graphe pondéré: les tables sont les nœuds, et une arête relie deux tables dès qu'une transaction au moins écrit dans les deux. Le poids de l'arête peut représenter le nombre de transactions, le nombre de lignes touchées ou la part des écritures de chaque table concernée par la paire.

Supposons que les traces normalisées arrivent dans une table nommée data_access:

create table data_access (
  captured_at timestamp not null,
  transaction_id varchar(100) not null,
  entry_point varchar(200) not null,
  table_name varchar(200) not null,
  operation varchar(10) not null,
  rows_affected bigint
);

with writes as (
  select distinct transaction_id, table_name
  from data_access
  where operation in ('INSERT', 'UPDATE', 'DELETE')
), pairs as (
  select a.table_name as table_a,
         b.table_name as table_b,
         count(*) as shared_transactions
  from writes a
  join writes b
    on a.transaction_id = b.transaction_id
   and a.table_name < b.table_name
  group by a.table_name, b.table_name
)
select table_a, table_b, shared_transactions
from pairs
order by shared_transactions desc;

La sortie prend la forme table_a | table_b | shared_transactions. Les valeurs les plus élevées méritent un examen, mais les nombres bruts ne suffisent pas. Un traitement d'entretien peut dominer le volume sans porter aucun invariant visible par l'utilisateur. Une rare comptabilisation de fin d'année peut contenir l'exigence atomique la plus forte du système. Ajoutez le point d'entrée au regroupement, puis comparez la même paire entre les requêtes en ligne, les traitements planifiés, les imports et les outils des opérateurs.

Normalisez le poids dans les deux directions. Si 98 pour cent des écritures dans customer_balance ont lieu avec ledger_entry, cette arête compte même lorsque ces transactions ne forment qu'une petite part de l'activité du grand livre. J'utilise deux mesures conditionnelles: les transactions qui écrivent A et B, divisées par toutes les transactions qui écrivent A, puis l'inverse. Un résultat asymétrique révèle souvent une table satellite qui appartient à un agrégat plus large.

L'échantillonnage doit préserver les frontières de transaction. Capturer une instruction SQL sur cent détruit les preuves, car l'échantillon peut garder une moitié d'une coécriture et perdre l'autre. Échantillonnez des transactions entières par leur identifiant, ou capturez toutes les transactions pour certains points d'entrée. Masquez les valeurs si nécessaire, mais conservez les noms de tables, les types d'opérations, les horaires et l'appartenance aux transactions.

Distinguer les invariants métier des habitudes d'implémentation

Un groupe dense de coécritures propose une frontière, il ne la prouve pas. L'équipe doit expliquer pourquoi chaque arête forte existe et ce qui casserait si les deux écritures étaient validées séparément. Cette explication distingue un invariant métier d'un code qui utilise la même connexion par commodité.

Demandez la phrase qui décrit l'échec. Pour une facture et son écriture au grand livre, elle pourrait être: «La comptabilité ne doit jamais reconnaître une facture sans les débits et crédits correspondants.» Pour une commande et sa ligne d'audit: «Les opérateurs ont besoin de savoir qui a modifié la commande.» La première peut exiger un état atomique ou un modèle de comptabilisation soigneusement revu. La seconde peut souvent passer par un événement durable ou une outbox de base de données sans intégrer la table d'audit à la propriété des commandes.

Classez chaque arête de coécriture parmi quatre causes:

  1. Un invariant métier exige que toutes les modifications réussissent ensemble.
  2. Un nettoyage référentiel ou une cascade maintient la cohérence des données stockées.
  3. Une valeur dérivée ou un index est mis à jour de façon synchrone pour accélérer les lectures.
  4. Le code a réutilisé une transaction parce que les tables étaient proches.

Seule la première cause indique fortement que les tables appartiennent à la même frontière de cohérence. La deuxième peut disparaître lorsqu'un service possède la suppression et publie le fait. La troisième relève généralement d'une projection. La quatrième est une dette de migration.

Les déclencheurs demandent une attention particulière, car les traces applicatives peuvent les cacher. Une routine semble mettre à jour shipment, alors qu'un déclencheur ajuste inventory, insère stock_movement et écrit dans une file d'intégration. Lisez les définitions des déclencheurs et le corps des procédures stockées, puis attribuez leurs écritures à la transaction et au point d'entrée d'origine. Sinon, la frontière proposée échouera au premier cas de production qui active ce comportement caché.

Les verrous et la gestion des erreurs apportent des preuves supplémentaires. Un code qui retente un interblocage sur deux tables, traduit la violation d'une contrainte en message métier ou annule les deux modifications après l'échec d'une validation dépend probablement de leur sort commun. Documentez la contrainte ou la règle de reprise exacte. «Ces tables sont couplées» reste trop vague pour guider une migration.

Traiter les lectures entre domaines comme une dette différente

Une lecture qui traverse les domaines envisagés n'invalide pas automatiquement la frontière. Les lectures peuvent passer par des API, des projections répliquées, des caches, des instantanés ou des magasins analytiques sans coordonner de commits. Il faut déterminer la fraîcheur et l'exhaustivité requises au moment où le lecteur prend sa décision.

Construisez une matrice de lecture une fois les propriétaires possibles des écritures identifiés. Les lignes représentent les points d'entrée, les colonnes les domaines proposés, et chaque cellule consigne les tables lues, la fréquence, la cardinalité et le fait que ce même point d'entrée écrive ou non ailleurs. Examinez surtout les lectures de décision, dont le résultat commande une écriture suivante. Un rapport qui joint facturation et clients peut tolérer une projection retardée. Un contrôle de crédit avant l'acceptation d'une commande peut exiger des données à jour ou un protocole de réservation.

Le motif dangereux consiste à lire le domaine B, calculer dans le code applicatif, puis écrire le domaine A en supposant que B n'a pas changé. Un monolithe local peut cacher cette course dans une transaction de base de données en verrouillant les lignes de B. Après la séparation, un appel d'API synchrone renvoie une valeur, mais n'étend pas la transaction de l'appelant sur le réseau. La valeur peut changer avant le commit de A.

Consignez une classe de fraîcheur pour chaque lecture transversale:

  • exacte au moment de la décision
  • retard borné avec un maximum défini
  • dernière valeur connue avec rapprochement
  • instantané historique
  • affichage uniquement

Cette classification transforme la vague dépendance «les commandes ont besoin des données client» en contrat. Le nom du client destiné au seul affichage peut vivre dans une projection des commandes. Un contrôle de plafond peut demander au domaine client de posséder une réservation. Le service de commande lui demande alors de réserver une capacité au lieu de récupérer un nombre et de décider lui-même.

Les jointures larges de reporting ne doivent pas fixer les frontières transactionnelles. Déplacez-les vers une projection de reporting alimentée par les modifications de leurs propriétaires, ou gardez un réplica de lecture pendant la transition. Obliger les services opérationnels à s'appeler ligne par ligne pour conserver un ancien rapport crée une jointure réseau lente et propage les indisponibilités. Les rapports ont besoin d'un produit de données explicite, pas d'un accès accidentel à tous les schémas opérationnels.

Les vues et les requêtes stockées peuvent masquer le franchissement. Développez chaque vue jusqu'à ses tables de base pour construire la matrice, tout en gardant son nom comme contrat du consommateur. Une douzaine de programmes peuvent lire open_account_summary sans savoir qu'elle joint les créances, le statut client et les litiges. Remplacer la vue une seule fois peut être plus simple que modifier chaque programme, mais sa règle de rafraîchissement a toujours besoin d'un propriétaire. Mesurez si les appelants filtrent, agrègent ou récupèrent le jeu complet pour choisir entre projection, point de requête et export en masse.

Étudiez aussi les lectures négatives. Le code demande souvent qu'une ligne n'existe pas: aucune facture impayée, aucun blocage actif, aucune requête antérieure avec cette référence. Le retard de réplication rend l'absence particulièrement dangereuse, car une projection obsolète ressemble exactement à une permission de continuer. Placez ces contrôles auprès des autres lectures de décision et nommez l'autorité capable d'y répondre. Si le contrôle protège une unicité ou un plafond de dépense, déplacez la décision vers cette autorité au lieu de copier la table et d'espérer gagner la course de réplication.

Le comportement en cas d'échec de lecture appartient aussi au contrat. Si le propriétaire distant est indisponible, l'appelant doit refuser, utiliser une valeur ancienne dans une limite donnée, mettre le travail en file ou continuer avec un risque explicite. Le bon choix dépend de la règle métier. Une politique générique de nouvelle tentative repousse la décision jusqu'à une panne, au moment où les opérateurs ont le moins de marge pour raisonner.

Une frontière échoue lorsque l'invariant la traverse

Garder le code réglementé dedans
Des modèles air-gapped tournent sur du matériel contrôlé quand le code ne peut quitter le périmètre.

Le test pratique d'une séparation proposée est simple: chaque côté peut-il accepter ou refuser ses propres commandes avec les données qu'il possède, tout en conservant les règles métier énoncées? Si une commande du côté A exige que le côté B participe au même commit, la frontière n'est pas prête.

Prenons une routine de commande qui exécute ces actions dans une transaction:

  1. Lire le crédit disponible du client avec un verrou de ligne.
  2. Insérer la commande et ses lignes.
  3. Augmenter l'encours engagé du client.
  4. Insérer une ligne d'audit et valider.

Un organigramme peut placer la gestion des clients et celle des commandes dans des départements différents. Une extraction directe transformerait les étapes deux et trois en transaction distribuée. Appeler d'abord le service client ne résout rien: l'insertion de la commande peut échouer après l'augmentation de l'encours. L'appeler en dernier produit l'orphelin inverse. Une nouvelle tentative aveugle risque de compter deux fois.

Trois solutions sont honnêtes. Conserver l'encours de crédit et l'acceptation de commande dans une même frontière. Déplacer la décision dans une réservation de crédit possédée par le domaine client, avec un identifiant de réservation idempotent et des opérations explicites de confirmation ou de libération. Ou changer la règle métier pour autoriser un désaccord temporaire, puis rapprocher les données et bloquer les commandes concernées. Chaque option change la propriété ou la sémantique. Un courtier de messages ne change rien à lui seul.

La réservation exige des états et un comportement temporel, pas un nom d'événement optimiste. reserve doit renvoyer le même résultat pour le même identifiant. confirm doit accepter les répétitions. L'expiration doit tenir compte d'une confirmation tardive. Les opérateurs doivent voir les réservations qui n'atteignent jamais un état final. Si l'organisation ne peut pas énoncer ces règles, elle n'a pas supprimé la transaction distribuée, elle a renommé l'incertitude.

C'est pourquoi je conteste «séparer par capacité métier» comme méthode complète. Ce conseil est populaire parce que les capacités donnent des diagrammes dont dirigeants et ingénieurs peuvent parler ensemble. Il est utile pour produire des candidats. Il est faux comme test final, car une carte de capacités ne révèle ni la portée des commits, ni les déclencheurs, ni les lectures de décision verrouillées, ni les règles de reprise.

Les traitements par lots révèlent ce que les traces en ligne ignorent

Le trafic en ligne couvre rarement le contrat complet d'un ancien système. Clôture mensuelle, règlement, imports, reprises et corrections des opérateurs traversent souvent des tables que les requêtes ordinaires ne touchent jamais. Une frontière choisie uniquement à partir des traces HTTP peut sembler nette jusqu'à la première exécution planifiée.

Inventoriez chaque exécutable qui se connecte à la base, dont les scripts lancés par les ordonnanceurs, les traitements stockés, les clients de bureau, les macros de feuilles de calcul et les outils de support. Reliez les sessions de base de données aux exécutables ou aux identifiants si possible. Les identifiants partagés compliquent cette tâche, alors combinez métadonnées de session, définitions d'ordonnancement, recherche dans les sources et journaux d'audit de la base.

La cadence des commits compte. Un programme qui lit toutes les factures non comptabilisées, crée les écritures, marque les lignes sources et valide tous les 500 éléments possède au moins trois portées:

  • la transaction de base de données de chaque lot
  • le point de reprise utilisé pour relancer l'exécution
  • l'exigence métier de toute la période comptable

Une séparation en services peut préserver les commits par lot tout en cassant la reprise. Imaginons que le nouveau service de grand livre accepte 430 écritures avant l'arrêt brutal de l'appelant. L'ancien programme repart de son dernier point de reprise et les renvoie. Sans identifiant source stable ni acceptation idempotente, la cible les comptabilise deux fois. Avec l'idempotence mais sans rapprochement, la source peut encore afficher 70 éléments en attente alors que le grand livre les a acceptés.

Parcourez un véritable chemin de reprise pour chaque lot important. Notez son point de reprise, les écritures faites avant ce point, la manière dont il reconnaît un travail antérieur, ce que les opérateurs examinent et comment il répare une exécution partielle. Attribuez ensuite la responsabilité de cette reprise. Les diagrammes de services omettent souvent les procédures opératoires, alors qu'elles contiennent parfois la seule définition de cohérence qui fonctionne.

Pondérez les traitements rares par leurs conséquences autant que par leur fréquence. Je marque une arête comme importante pour les opérations lorsqu'un échec bloque une clôture, une paie, une expédition, un rapport réglementaire ou un autre événement métier nommé. C'est un jugement, pas un faux score mathématique. Il empêche les nombreuses mises à jour de connexion de masquer un invariant comptable peu fréquent.

Attribuer les tables avant de choisir les API

Réécrire l'ancienne pile
RPG, VB6, ColdFusion, Perl et d'autres sources anciennes peuvent devenir Go, Rust et TypeScript.

Chaque table modifiable doit avoir un propriétaire proposé avant la conception des API. Un accès en écriture partagé permet aux deux services de garder les anciens raccourcis, donc la frontière n'existe que dans les diagrammes de déploiement. La propriété signifie qu'un service décide des transitions d'état valides, écrit et gère les réparations.

Créez un registre avec ces colonnes: table, propriétaire proposé, points d'entrée qui écrivent, groupe de coécriture, lectures de décision transversales, déclencheurs, traitements par lots et invariant non résolu. Attribuez aussi les tables dérivées. «Partagé» est un état de migration temporaire avec une condition de sortie, pas un domaine.

Cherchez ensuite chaque chemin d'écriture dans tout l'arbre source. La recherche statique trouve les instructions et correspondances ORM absentes des traces. Les traces dynamiques trouvent le SQL produit et les appels de procédures peu visibles que la recherche a manqués. Aucune source ne suffit seule. Comparez-les et expliquez les écarts, surtout les utilitaires dormants qui possèdent encore des identifiants de production.

Les commandes d'API doivent exprimer les décisions possédées par le service appelé. reserveCredit(orderId, amount) est plus solide que getAvailableCredit(customerId) suivi d'un calcul chez l'appelant. postInvoice(invoiceId, lines) est préférable à des opérations CRUD exposées sur les tables du grand livre. La commande permet au propriétaire de protéger son invariant pendant que son stockage change.

Les lectures ont aussi besoin d'une propriété, même si les données sont copiées. Une projection peut contenir le nom et le statut du client dans le service de commande, mais le service client reste l'autorité. Stockez l'identifiant et la version de source ou la position d'événement afin que le rapprochement détecte les mises à jour perdues ou inversées. Décidez ce que fait le lecteur quand la projection est obsolète: poursuivre, avertir, refuser ou appeler de façon synchrone. Ne laissez pas ce choix à l'ingénieur chargé du premier incident.

Les permissions de base de données peuvent imposer la frontière avant l'extraction physique. Donnez les droits d'écriture au futur propriétaire et transformez progressivement les autres écrivains en appelants. Auditez les tentatives refusées pendant les tests. Une séparation de schéma sans changement de permissions reste cosmétique, car tout ancien traitement peut encore la traverser.

Évaluer les frontières par le travail qu'elles demandent

Une évaluation utile estime le coût de migration et le risque opérationnel, elle ne prétend pas découvrir l'architecture par l'arithmétique. Je compare les candidats avec la même série de questions observables et je conserve les preuves brutes à côté de chaque appréciation.

Pour chaque frontière proposée, consignez:

  • le nombre et l'importance métier des transactions qui écrivent des deux côtés
  • les lectures de décision exigeant un état distant actuel
  • les lots et les chemins de reprise qui traversent la ligne
  • les tables ayant plusieurs écrivains actifs
  • les rapports et exports qui ont besoin d'un nouveau chemin de lecture

Utilisez une petite échelle ordinale telle que absent, gérable, important et bloquant. Ne réduisez pas tout à un nombre décimal. Deux candidats ayant le même total peuvent porter des risques très différents: l'un demande plusieurs projections simples, l'autre contient un seul invariant financier bloquant. Ce dernier commande la décision.

La meilleure première frontière présente généralement des écritures cohésives et des lectures sans histoire. Un groupe possède ses mises à jour, tandis que les consommateurs externes affichent ou rapportent surtout ses données. Cette forme se prête à une outbox, à des projections et à une petite surface de commandes. La pire frontière peut compter peu de tables évidentes, mais beaucoup de lectures de décision à jour et d'écrivains partagés. Un petit schéma ne signifie pas un faible couplage.

La fenêtre temporelle change le résultat. Analysez des périodes métier représentatives, y compris les exécutions planifiées et les rares actions d'opérateurs. Comparez les jours normaux aux périodes de clôture ou de règlement. Une matrice construite pendant un après-midi calme sous-estime le couplage. L'analyse du code doit compléter la fenêtre en listant les points d'entrée absents du trafic capturé.

Rendez l'incertitude visible. Marquez les tables dont les traces sont incomplètes, les noms dynamiques, les écrivains externes ou les procédures inconnues. Une arête non résolue ne vaut pas zéro. Je retarderais une décision autour d'une routine comptable inconnue plutôt que de faire confiance à un graphe propre produit par des preuves partielles.

Prouver la frontière par un comportement parallèle

Traiter le monolithe entier
Les systèmes de plus d'un million de lignes sont lus comme un ensemble avant leur séparation.

Une frontière mérite la confiance quand les propriétaires proposés reproduisent les résultats actuels sur des charges enregistrées sans partager les écritures. Avant d'envoyer les commandes de production aux nouveaux services, exécutez l'architecture candidate en parallèle et comparez ses transitions d'état à celles de l'original.

Le banc doit rejouer les commandes ou le trafic capturé avec des identifiants stables, observer les effets en base et comparer les résultats métier plutôt que l'ordre physique des lignes. Normalisez les horodatages, les identifiants générés et les autres champs non déterministes. Comparez les totaux, statuts, faits émis, classes d'erreur et résultats de reprise. Un écart demande une explication classée, pas un pourcentage global de réussite.

Incluez les cas qui sollicitent la frontière:

  1. commandes réussies dont les écritures restent chez un seul propriétaire
  2. commandes refusées après une réservation ou validation distante
  3. nouvelles tentatives après un délai dépassé et une livraison en double
  4. reprise d'un lot depuis chaque position de contrôle
  5. données de projection absentes ou obsolètes

Le trafic enregistré apporte du réalisme, mais contient rarement toutes les pannes. Ajoutez des fautes contrôlées entre les étapes qui partageaient auparavant un commit. Arrêtez le consommateur après son écriture mais avant l'acquittement. Retardez une mise à jour de projection. Répétez un identifiant de commande. Faites expirer une réservation au moment où la confirmation arrive. Ces tests montrent si la nouvelle conception prévoit une reprise explicite.

CodeHero utilise un banc de parité avec le trafic de production enregistré lorsqu'il réécrit les anciens systèmes. Cette approche convient ici, car une modification d'architecture n'est crédible que si le comportement reste redevable à l'original. Les preuves doivent rester lisibles par les ingénieurs du client: identité de l'entrée, ancien résultat, nouveau résultat, différences normalisées et règle d'acceptation ou de rejet.

N'exigez pas l'égalité octet par octet quand la migration change volontairement l'architecture. Exigez l'égalité du comportement promis et une acceptation documentée des différences voulues. Si l'ordre comptable change mais que soldes, références et règles de reprise restent corrects, la séquence physique peut être indifférente. Si une erreur devient un succès après un délai dépassé, cela compte même si les décomptes finaux de tables sont identiques.

La première extraction doit supprimer une frontière transactionnelle

Ne choisissez le premier service qu'après avoir nommé ses tables, ses commandes, ses faits publiés, ses lectures transversales et ses règles de reprise. L'équipe doit pouvoir désigner chaque ancienne écriture traversant la frontière et dire si elle a été supprimée, convertie en commande possédée ou acceptée comme contrainte temporaire avec une condition de sortie datée.

J'utilise un seul critère de mise en production: aucun chemin de production ne doit écrire des tables des deux côtés de la frontière proposée. Les doubles écritures temporaires dans un adaptateur de migration comptent encore comme transversales. Elles demandent idempotence, comparaison et plan de retrait, mais ne prouvent pas une propriété indépendante.

La séquence d'extraction suit les preuves. Imposez d'abord un écrivain par table. Remplacez ensuite les lectures d'affichage et de reporting par des projections ou un accès transitoire approuvé. Déplacez les lectures de décision vers des commandes du propriétaire ou des protocoles de réservation explicites. Modifiez enfin les frontières de déploiement et de stockage. L'ordre inverse crée des appels réseau tout en conservant l'ancien couplage des données.

Gardez les matrices de coécriture et de lecture après l'extraction. Elles deviennent des contrôles de régression. Un nouvel écrivain partagé, une commande qui commence à lire un état distant actuel ou un traitement qui contourne l'API doit provoquer une revue. Les diagrammes d'architecture vieillissent en silence, les preuves d'accès révèlent la brèche.

Certains systèmes contiennent un invariant qui doit rester local. Acceptez ce résultat. Un service plus grand avec une transaction cohérente coûte moins cher et offre plus de sécurité que deux services tenus ensemble par des appels synchrones, des verrous distribués et des réparations manuelles. Le but est de permettre le changement indépendant là où les règles métier l'autorisent, pas de maximiser le nombre de déploiements.

Lorsque les preuves soutiennent la séparation, la frontière cesse d'être une opinion sur des noms. Elle devient une affirmation réfutable: ces tables changent ensemble, ces lectures tolèrent ce contrat, ces commandes protègent l'invariant et ces tests de panne démontrent une reprise indépendante. Cela suffit pour passer d'une frontière d'atelier à une frontière de production.

FAQ

Quelle est la preuve la plus forte d'une frontière de service?

Les tables qui changent régulièrement dans une même transaction fournissent la première preuve la plus forte, car le système donne un résultat commun à ces écritures. Vérifiez la raison de la coécriture avant de déclarer une frontière, car certaines transactions communes relèvent de la commodité et non d'une règle métier.

Les clés étrangères définissent-elles les frontières de service?

Non. Les clés étrangères montrent des relations référentielles déclarées, alors que les frontières dépendent de la propriété des écritures, des décisions, de la reprise et de la cohérence acceptable. Les dépendances non déclarées des procédures et des lots comptent souvent davantage que la contrainte du schéma.

Quel volume de trafic de production faut-il capturer pour l'analyse?

Capturez des transactions complètes sur des périodes métier représentatives, avec les traitements planifiés, les clôtures, les imports et les corrections des opérateurs. Un nombre fixe de jours est moins utile que la couverture de chaque point d'entrée et chemin de reprise important.

Toute lecture entre domaines exige-t-elle une API synchrone?

Non. L'affichage, le reporting et les lectures historiques conviennent généralement à des projections, des instantanés ou des exports en masse. Utilisez une commande possédée ou une réservation lorsque la lecture commande une écriture et exige un état actuel.

Comment trouver les accès cachés dans les procédures et déclencheurs?

Inspectez leurs définitions, combinez-les aux traces d'audit de la base et rattachez leurs lectures et écritures à la transaction d'origine. Les traces applicatives seules peuvent faire passer une opération sur plusieurs tables pour une écriture unique.

Un courtier de messages supprime-t-il le besoin d'une transaction distribuée?

Un courtier transporte des messages, il ne décide pas de l'invariant. Il faut toujours des transitions d'état possédées, de l'idempotence, des règles de nouvelle tentative, un rapprochement et une règle pour le progrès partiel.

Les jointures de reporting doivent-elles influencer les frontières opérationnelles?

Elles doivent influencer la conception des lectures, pas celle des transactions. Alimentez une projection de reporting avec les modifications de leurs autorités au lieu d'imposer des jointures réseau ligne par ligne aux services opérationnels.

Que faire si deux domaines exigent vraiment des écritures atomiques?

Gardez l'invariant dans un service, introduisez un protocole de réservation explicite ou changez la règle pour autoriser un désaccord temporaire avec rapprochement. Si aucune solution n'est acceptable, la séparation proposée est mal placée.

Comment imposer la propriété des tables avant l'extraction?

Donnez l'écriture à un futur propriétaire, faites passer les autres écrivains par ses commandes et auditez les refus pendant les tests. Cela expose les traitements et utilitaires oubliés avant qu'un déplacement physique de la base augmente le coût d'une erreur.

Comment prouver qu'une frontière choisie fonctionne?

Rejouez des charges enregistrées par les propriétaires proposés et comparez les résultats métier, les nouvelles tentatives, les reprises de lots et les pannes avec l'original. La frontière est crédible quand aucun côté ne doit écrire les tables de l'autre ni rejoindre son commit.