Distributed Pattern Diagrams

Last updated:

Four Communication Patterns

Flow

Request-response, scatter-gather, publish-subscribe, and event streaming.

Request-response, scatter-gather, publish-subscribe, and event streaming Request-response: the client sends a request and waits for one response. Scatter-gather: a client asks an aggregator, which fans the request out to services A, B, and C in parallel and returns one combined result. Publish-subscribe: a publisher sends one message to a topic, and each of subscribers A, B, and C gets its own copy. Event streaming: a producer appends events e1 to e6 to an ordered, retained log, and consumers A and B each read at their own offset. REQUEST-RESPONSE: THE CALLER WAITS Client Service request response SCATTER-GATHER: FAN OUT, ONE ANSWER Client Aggregator Service A Service B Service C one combined result PUBLISH-SUBSCRIBE: A COPY FOR EVERY SUBSCRIBER Publisher topic Subscriber A Subscriber B Subscriber C EVENT STREAMING: A RETAINED, ORDERED LOG Producer e1 e2 e3 e4 e5 e6 Consumer A offset Consumer B offset events stay after they are read

Fan-Out and Competing Consumers

Flow

Every subscription gets a copy; one instance per subscription takes it.

Fan-out across subscriptions and competing consumers within one A publisher sends an order placed message to a topic. The topic delivers a copy to every subscription: inventory, payment, and notification. Within the payment subscription, three instances of the payment service compete, and each message goes to only one of them. Fan-out decides which services hear about a message. Competing consumers decide how one service scales its processing. Publisher Topic order placed INVENTORY SUBSCRIPTION one instance PAYMENT SUBSCRIPTION instance 1 instance 2 instance 3 this message next message may go to another instance NOTIFICATION SUBSCRIPTION one instance FAN-OUT every subscription gets its own copy COMPETING CONSUMERS one instance takes each message copy of the message delivered to one instance

Transactional Outbox

Flow

The event commits with the data, and a relay publishes it afterward.

Transactional outbox pattern A service inserts an order into its business tables and an event into an outbox table inside one database transaction, so both commit or roll back together. Outside that transaction, a message relay, either a polling publisher or transaction log tailing, reads the outbox and publishes to the broker, which delivers to the consumer. Service ONE DATABASE TRANSACTION Business tables INSERT order Outbox table INSERT event Both rows commit or roll back together. Message relay polling or log tailing outside the transaction reads unpublished rows Broker Consumer publish

Claim Check

C4 · Dynamic

The payload goes to storage; only a reference crosses the broker.

Claim check sequence The producer stores the payload and gets back a claim check id. It sends a small message carrying only that reference through the broker, which delivers it to the consumer. The consumer fetches the payload from storage using the id, and optionally deletes it last, after acknowledging the message. Producer Storage Message broker Consumer 1. store payload claim check id 2. send message with the id only 3. deliver 4. fetch payload using the id payload 5. delete, last, after the ack (optional)

Dead Letter Queue

Flow

A message that keeps failing moves aside so the queue keeps flowing.

Dead letter queue flow Message A fails processing and is retried three times, failing each time. After the last retry, the broker moves it to a dead letter queue with its failure count, reason, and timestamp, where it waits for manual review or automated replay. Messages B and C behind it keep flowing to the consumer. MAIN QUEUE C B A Consumer processes fail, retry 1, 2, 3 B and C keep flowing instead of queuing behind A DEAD LETTER QUEUE Message A failed 3 times reason: timeout timestamp Manual review or automated replay move after the last retry

Priority Queues

Flow

Three queues, drained by priority rather than arrival order.

Priority queue with strict ordering Incoming messages go to a HIGH, MEDIUM, or LOW queue by priority. The consumer processes HIGH first, then MEDIUM, and serves LOW only when both higher queues are empty. priority: high HIGH (P1) priority: medium MEDIUM (P2) priority: low LOW (P3) Consumer 1. first 2. then 3. only when HIGH and MEDIUM are empty

Database per Service Versus Shared Database

Structure

Three services with their own databases, or one database for all.

Database per service compared with a shared database On the left, orders, billing, and search each own a database. A cross-service read becomes an API call, a cross-service write takes many steps, and a schema change involves one team. On the right, the three services share one database. A cross-service read is a join, a cross-service write is one transaction, and a schema change involves every team. DATABASE PER SERVICE SHARED DATABASE Orders orders db Orders Billing billing db Billing Search search db Search one database cross-service read an API call cross-service read a join cross-service write many steps cross-service write one transaction schema change one team schema change every team

The Eventual Consistency Window

Chart

Two copies disagree between a write and convergence.

Eventual consistency window between a write model and a read model A timeline with two rows. The write model changes from the old value to the new value when a write commits. The read model keeps the old value until it catches up some time later. Between the two moments is the window, when the copies disagree. The user who just made the write, reading during the window, sees the old value. A reader after the window sees the new value. the window: the copies disagree Write model old value new value Read model old value new value the writer reads here: old value a later reader sees the new value time write commits read model catches up

State-Based Storage Versus Event Sourcing

Structure

Current state stored, or derived by replaying every change.

State-based storage compared with event sourcing State-based storage keeps one account record with id 123, balance 120 dollars, and status active, holding only current state. Event sourcing keeps an event store with AccountOpened, Deposited 100 dollars, Withdrawn 30 dollars, and Deposited 50 dollars. Replaying all four gives the current balance: 0 plus 100 minus 30 plus 50, which is 120 dollars. STATE-BASED Account id: 123 balance: $120 status: active only current state is stored, each change overwrites it EVENT SOURCING Event store: immutable events 1. AccountOpened(id: 123) 2. Deposited($100) 3. Withdrawn($30) 4. Deposited($50) Current state replay all: 0 + 100 − 30 + 50 = $120 replay

Snapshots in an Event Store

Structure

Replay starts from the latest snapshot, not from event one.

Reading state from the latest snapshot in an event store An event log holds events 1 to 1000, a snapshot at 1000 with a balance of 5000 dollars, events 1001 to 2000, a snapshot at 2000 with a balance of 7500 dollars, and events 2001 onward. To read state at event 2347, load the snapshot at 2000 and replay only events 2001 to 2347. events 1–1000 snapshot @ 1000 $5000 events 1001–2000 snapshot @ 2000 $7500 events 2001–2347 load the snapshot, replay only what follows skipped To read state at event 2347:

CQRS

Flow

Writes and reads go to separate models, synced after commit.

Command query responsibility segregation Commands go to a command model normalized for correctness. After a write commits, a sync mechanism, using events, change data capture, or polling, updates a query model denormalized for the queries it serves. Queries read from the query model. Commands (writes) Queries (reads) Command model [normalized for correctness] Query model [denormalized per query] Sync mechanism events, CDC, or polling after the write commits

Orchestration and Choreography

Flow

One service calling the others in order, or services reacting to an event.

Orchestration compared with choreography In orchestration, an order orchestrator holds the process state and calls payment, inventory, shipping, and notification services in order, waiting for each response. The participants know nothing about the process. In choreography, the order service publishes an OrderCreated event to an event bus, and the inventory, payment, shipping, and notification services each react to it. No service owns the process. ORCHESTRATION Order orchestrator holds the process state Payment 1 Inventory 2 Shipping 3 Notification 4 Calls each in order and waits; participants know nothing about the process. CHOREOGRAPHY Order service event bus OrderCreated Payment Inventory Shipping Notification Each reacts on its own; the workflow is only the sum of those reactions. call and response event

One Transaction Versus Separate Databases

Structure

One all-or-nothing commit, or three local commits with nothing tying them.

A single database transaction compared with separate service databases In a monolith, one transaction inserts the order, updates inventory, and inserts the payment, and commits all or nothing. With microservices, the order, payment, and inventory services each own a database and commit locally, and no shared transaction covers the three. ONE DATABASE BEGIN TRANSACTION INSERT order UPDATE inventory INSERT payment COMMIT: all or nothing SEPARATE DATABASES Order own DB local commit Payment own DB local commit Inventory own DB local commit No transaction covers all three. transaction boundary

A Saga Succeeding and Compensating

Flow

Each step commits locally; a failure runs compensations in reverse.

Saga happy path and failure path with compensation On the happy path, the saga creates the order as pending, reserves inventory, charges payment, and completes the order. On the failure path, the payment charge is declined at step 3, so the saga runs the compensations for the steps that already committed in reverse order: first releasing inventory, the compensation for step 2, then cancelling the order, the compensation for step 1. HAPPY PATH: EVERY STEP COMMITS Create order T1, pending Reserve inventory T2 Charge payment T3 Complete order confirmed STEP 3 FAILS: COMPENSATE IN REVERSE Create order T1 Reserve inventory T2 Charge payment T3 ✗ payment declined Release inventory C2, undoes T2 Cancel order C1, undoes T1 first then

Compensatable, Pivot, and Retriable Steps

Flow

The pivot is the point of no return in a saga.

Compensatable, pivot, and retriable saga steps Five saga steps in order. CreateOrder and ReserveInventory are compensatable, with CancelOrder and ReleaseInventory as their compensations. ChargePayment is the pivot, the go or no-go point. After it commits, the saga is committed to finishing. ShipOrder and SendConfirmation are retriable: no compensation exists, so the saga retries each until it succeeds. T1 CreateOrder C1: CancelOrder T2 ReserveInventory C2: ReleaseInventory T3 ChargePayment C3: RefundPayment T4 ShipOrder no compensation T5 SendConfirmation no compensation COMPENSATABLE: CAN BE UNDONE PIVOT RETRIABLE: RETRIED UNTIL THEY SUCCEED point of no return: once the pivot commits, the saga is committed to finishing

An Orchestrated Saga

C4 · Dynamic

The orchestrator holds saga state and calls the compensations itself.

Orchestrated saga with compensation A saga orchestrator holds the saga state for order 123. It calls the order service to create the order, which succeeds, then the inventory service to reserve stock, which succeeds, then the payment service to charge, which fails. It then calls the inventory service to release the stock, compensating step 2, and the order service to cancel, compensating step 1. The shipping service is never called. Saga orchestrator saga state: orderId 123, step PAYMENT Order service Inventory service Payment service Shipping service 1 create 5 cancel 2 reserve 4 release 3 charge: FAILED never called 4 compensates T2 and 5 compensates T1, in reverse order. forward step failed step compensation

A Choreographed Saga

Flow

A failure event travels upstream and each service compensates itself.

Choreographed saga with compensation The order service publishes OrderCreated, the inventory service reserves stock and publishes InventoryReserved, and the payment service fails and publishes PaymentFailed. That failure event reaches every upstream participant: the inventory service releases stock and publishes InventoryReleased, and the order service cancels and publishes OrderCancelled. No single place holds the saga state. Order service Inventory service Payment service OrderCreated InventoryReserved PaymentFailed cancels, then publishes OrderCancelled releases, then publishes InventoryReleased Saga state is implied by which events have been published. No single place holds it. event failure event, sent upstream

Leader Failover

State machine

The leader fails, followers notice, and a new leader is chosen.

Leader failover in a three-node group Three states of a three-node group. First, node 1 is the leader and nodes 2 and 3 are followers. Second, node 1 fails and the followers detect the failure through a heartbeat timeout. Third, a new election makes node 2 the leader, node 3 stays a follower, and node 1 remains down. 1. STEADY STATE Node 1: leader Node 2: follower Node 3: follower 2. LEADER FAILS Node 1: failed ✗ Node 2: follower Node 3: follower Followers detect the failure through a heartbeat timeout. 3. NEW ELECTION Node 1: down ✗ Node 2: leader Node 3: follower A new leader is chosen.

Leader Lease

Chart

A crashed leader's lease runs out before anyone else leads.

Leader lease timeline A timeline with two rows. Node 1 acquires a lease at T=0 that expires at T=10 and renews it at T=5 so it expires at T=15. Node 1 crashes at T=8 and stops renewing, but its lease is still held until it expires at T=15. Node 2 is a follower until T=16, when it acquires a new lease and becomes leader. From T=8 to T=15 there is no leader, which is safer than two. T=8 to T=15: no leader, which is safer than two Node 1 acquire: expires T=10 renew: expires T=15 leader crashed, lease still held Node 2 follower leader new lease time T=0 T=5 T=8 crash, renewals stop T=10 T=15 lease expires T=16

Lost Update Without a Lock

Flow

Two read-modify-writes race, and a distributed lock serializes them.

A lost update without a lock, and the same updates under a distributed lock Two panels, time running downward. Without a lock, node A and node B both read 10. A adds 5 and writes 15, B adds 3 and writes 13, and the final value is 13 because A's update was lost. With a distributed lock, A acquires the lock while B's acquire is blocked. A reads 10, adds 5, writes 15, and releases. B then acquires the lock, reads 15, adds 3, and writes 18, so the final value is 18. time WITHOUT A LOCK Node A Node B read 10 add 5 write 15 read 10 add 3 write 13 Final value: 13 (lost update) WITH A DISTRIBUTED LOCK Node A Node B acquire read 10 add 5 write 15 release acquire blocked, waiting acquire read 15 add 3 write 18 Final value: 18

Lock Expiry Under a Paused Holder

Flow

A paused holder's lock expires, and it writes anyway.

A lock expires while its holder is paused A timeline with two rows. Node A acquires the lock, then enters a long garbage collection pause. During the pause the lock expires, and node B acquires it and writes successfully. Node A then wakes and writes, unaware that its lock expired, so its write is stale. Node A's lock expires Node A acquire lock long GC pause write ✗ stale Node B acquire lock write ✓ time

Fencing Token

Flow

The storage rejects a write whose token is older than one it has seen.

Fencing tokens reject a stale write A timeline with three rows. Node A acquires the lock with token 33, then pauses for a long time. Node B acquires the lock with token 34 and writes with token 34, which the storage accepts, and from then on the storage requires a token of at least 34. Node A wakes and writes with token 33, and the storage rejects it. Node A lock, token 33 long pause write(token 33) Node B lock, token 34 write(token 34) Storage accepted REJECTED: 33 < 34 From here the storage requires a token of at least 34. time

Consensus Write Path

C4 · Dynamic

A write commits once a majority of the cluster acknowledges it.

A write replicated through a three-node consensus group A client sends a write request to the leader. The leader appends the entry to its log and replicates it to follower 1 and follower 2. When a majority, two of three nodes, has acknowledged, the entry is committed and the leader replies to the client. Client CONSENSUS GROUP, 3 NODES Leader appends entry to its log Follower 1 Follower 2 1. write request 4. reply 2. replicate 3. ack 3. ack Committed once a majority (2 of 3) has acknowledged. request or replication acknowledgement

Retry Waves and Jitter

Chart

Clients that fail together retry together, unless jitter spreads them.

Retry arrivals with exponential backoff, without and with jitter Two rows of retry arrivals over time from many clients that failed at the same moment. With exponential backoff alone, every client retries after the same delays, so the retries arrive in synchronized waves after 1, 3, and 7 seconds. With full jitter, each client picks a random delay up to the exponential value, so the same retries are spread across the interval in much lower bars. The bars are illustrative, not measured. Backoff no jitter Backoff full jitter attempt 1 attempt 2 attempt 3 0s 1s 2s 3s 4s 5s 6s 7s 8s Retries arriving at the service from many clients that failed at the same moment

Circuit Breaker States

State machine

Closed, open, and half-open, and what moves the breaker between them.

Circuit breaker state machine Three states. Closed lets calls pass. When failures cross the threshold it moves to open, which fails calls fast. When the break duration elapses it moves to half-open, which allows one trial call. If the trial call fails the breaker returns to open, and if it succeeds the breaker returns to closed. CLOSED calls pass OPEN fail fast HALF-OPEN one trial call failures over threshold break duration elapses trial call fails trial call succeeds

Bulkheads

Structure

A hung dependency fills one shared pool, or only its own partition.

A shared connection pool compared with bulkheaded pools Two panels. Without bulkheads, checkout, search, and reports requests all draw from one shared pool of 70 slots. When the reporting database hangs, its calls hold all 70 slots and checkout and search stall too. With bulkheads, checkout has a pool of 40 slots to the payment API, search has 20 to the search index, and reports have 10 to the reporting database. When the reporting database hangs, its 10 slots fill and further report calls are rejected, while checkout and search keep their own slots. WITHOUT BULKHEADS Checkout Search Reports shared pool 70 of 70 held Payment API Search index Reporting DB Reporting DB hangs, and its calls hold all 70 slots. Checkout and search stall too. WITH BULKHEADS Checkout Search Reports pool: 40 pool: 20 10 of 10 held Payment API Search index Reporting DB Reporting DB hangs, and its 10 slots fill. Further report calls are rejected. Checkout and search keep their own slots.

Resilience Layers

Layering

Total timeout, retry, circuit breaker, and attempt timeout, outermost first.

Resilience strategies layered around a dependency call Four nested layers around a call to a dependency. The outermost is the total timeout, covering the whole operation with retries included. Inside it is the retry layer, using backoff with jitter and capped attempts. Inside that is the circuit breaker, which counts every attempt and fails fast when open. Innermost is the attempt timeout for one call, which wraps the call to the dependency. The request enters from the outside. Request Total timeout the whole operation, retries included Retry backoff with jitter, capped attempts Circuit breaker counts every attempt, fails fast when open Attempt timeout one call Dependency

Layer 4 and Layer 7 Balancing

Flow

One HTTP/2 connection, balanced as a connection or as requests.

Layer 4 balancing compared with layer 7 balancing for one HTTP/2 connection Two panels. A client holds one HTTP/2 connection to a load balancer. A layer 4 balancer balances connections, so all 500 requests on that connection go to instance A and instance B sits idle. A layer 7 balancer balances requests, so about 250 go to instance A and about 250 to instance B. LAYER 4: BALANCES CONNECTIONS Client one HTTP/2 connection LB Instance A Instance B all 500 requests idle LAYER 7: BALANCES REQUESTS Client one HTTP/2 connection LB Instance A Instance B ≈250 requests ≈250 requests

Fixed Window Boundary Burst

Chart

Two full windows back to back let double the limit through.

A fixed window rate limit allowing a burst across a window boundary A timeline from 12:00:00 to 12:02:00 split into two one-minute windows with a limit of 100 requests each. 100 requests arrive at 12:00:59, at the end of the first window, and another 100 at 12:01:00, at the start of the second. Each window stays within its limit, yet 200 requests arrive within two seconds. Window 1 100 of 100 allowed Window 2 100 of 100 allowed 100 at 12:00:59 100 at 12:01:00 200 requests within two seconds 12:00:00 12:01:00 12:02:00 Limit: 100 requests per one-minute window

Cache-Aside and Read-Through

Flow

Who talks to the database: the application, or the cache.

Cache-aside compared with read-through and write-through caching Two panels. In cache-aside, the application first gets from the cache, and on a miss it queries the database and then sets the value in the cache, so the application owns both calls. In read-through and write-through, the application only gets from and sets to the cache, and the cache loads from and stores to the database, so the cache owns the database access. CACHE-ASIDE App Cache DB 1. get miss 2. query 3. set The app owns both calls. READ-THROUGH / WRITE-THROUGH App Cache DB get / set load / store The cache owns the database access.

Sharding by Key Range

Structure

One overloaded database split into three shards, with queries routed by key.

A database before and after sharding by username range Before sharding, a single overloaded database holds 100 million users. After sharding, three shards hold users A to H, I to P, and Q to Z. The application routes a query for the username john_doe to shard 1, which holds I to P, and queries only that shard. BEFORE SHARDING Single database 100M users overloaded AFTER SHARDING Application routeToShard("john_doe") → Shard 1 (I-P) Shard 0 users A-H Shard 1 users I-P Shard 2 users Q-Z query by username

Consistent Hashing Ring

Dependency graph

A new shard takes keys from one neighbor and leaves the rest in place.

Adding a shard to a consistent hashing ring A ring of hash values with shards A at the top, D on the right, B at the bottom, and C on the left. Each key belongs to the first shard found moving clockwise from it. Shard D is new. It takes only the keys on the arc between A and D, which previously belonged to B. Keys on every other arc stay where they were. clockwise A D B C new shard A key belongs to the first shard found moving clockwise from it. Keys between A and D moved from B to D, the only keys that moved. Every other key stays where it was. Going from 3 shards to 4 moves roughly a quarter of the keys, not three quarters.

Where Each Proxy Sits

C4 · Container

BFFs per client experience, one gateway, and proxies beside each service.

API gateway, backends for frontends, sidecars, and an ambassador in one system A web app calls a web BFF and a mobile app calls a mobile BFF, one BFF per client experience. Both BFFs call one API gateway, which handles all external traffic. The gateway routes to the orders service and the billing service, each running with a sidecar, one per service instance. The orders service calls an external API through an ambassador. Web app Mobile app Web BFF Mobile BFF API Gateway Orders sidecar Billing sidecar Ambassador External API one per client experience one for all external traffic one per service instance

Sidecar Proxy

C4 · Deployment

All traffic in and out of the pod passes through the sidecar.

A sidecar proxy beside an application in one pod A pod runs the application alongside an Envoy proxy sidecar. Inbound traffic enters the pod through Envoy, which passes it to the application. The application's outbound calls also go through Envoy before leaving the pod. Envoy applies mutual TLS, retries, and tracing without any change to the application code. POD Envoy proxy [Container: sidecar] mutual TLS, retries, tracing Application [Container: unchanged code] inbound traffic in out outbound calls

Ambassador

C4 · Deployment

The application calls localhost, and the ambassador makes the real call.

An ambassador handling an application's outbound call An application calls the ambassador on localhost as if it were the remote service. The ambassador, running beside the application, handles service discovery, TLS origination, and timeouts, retries, and circuit breaking, then calls the external payment API over TLS. SERVICE INSTANCE Application Ambassador • service discovery • TLS origination • timeouts, retries, circuit breaking localhost External payment API TLS

Mesh Control and Data Planes

C4 · Container

The control plane configures proxies, and only the proxies carry requests.

Service mesh control plane and data plane The control plane, responsible for configuration, identity, and certificates, takes in operator policy and watches services and endpoints in the platform. It pushes configuration and certificates to the proxies. In the data plane, service A talks to its proxy, which connects over mutual TLS to service B's proxy, which talks to service B. Request traffic flows only through the data plane. Control plane config · identity · certs operator policy watches services and endpoints in the platform pushes config and certificates DATA PLANE (REQUEST TRAFFIC) Service A proxy proxy Service B mTLS request traffic configuration, never requests

Sidecar and Sidecarless Data Planes

C4 · Deployment

A proxy in every pod, or one per node plus shared layer 7 proxies.

Sidecar data plane compared with a sidecarless per-node data plane Two panels. In the sidecar model, each pod on a node holds a service and its own proxy, one proxy per instance handling layer 4 and layer 7 for that instance. In the sidecarless model, pods hold only their services, and a node proxy shared by the pods on that node handles layer 4 work such as mutual TLS and identity. Only where layer 7 policy applies does traffic also pass through a shared layer 7 proxy per service or namespace, outside the node. SIDECAR MODEL Node Pod Service A proxy Pod Service B proxy Pod Service C proxy One proxy per instance, handling L4 and L7 for that instance. SIDECARLESS (PER-NODE) MODEL Node Pod Service A Pod Service B node proxy L4: mTLS, identity shared L7 proxy per service or namespace only where L7 policy applies

Weighted Traffic Split

Flow

The caller's proxy sends 90% to the stable version and 10% to the canary.

A canary release through weighted traffic splitting A caller's requests pass through its proxy, which splits them: 90 percent go to reviews version 1, the stable version, and 10 percent to reviews version 2, the canary. caller proxy applies the split reviews v1 stable reviews v2 canary 90% 10%

Mesh Ingress and Egress Gateways

Trust boundary

One controlled path into the mesh and one controlled path out.

Ingress and egress gateways at the mesh boundary An external client's traffic enters the mesh through an ingress gateway, which handles external TLS and mesh routing. Inside the mesh, where traffic uses mutual TLS, the request goes to service A and then service B. Service B's call to an external API leaves through an egress gateway, which applies an allow list and audit, and TLS toward the external API is originated at the gateway. External client External API MESH (mTLS INSIDE) Ingress gateway external TLS, mesh routing Egress gateway allow list, audit Service A Service B TLS originated at the gateway

Strangler Fig Stages

Flow

A router moves capabilities to new code until the legacy system retires.

Three stages of a strangler fig migration Three stages. In stage 1, requests reach a router that sends all of them to the legacy monolith. In stage 2, the router sends /orders to a new orders service and everything else to the legacy system, which has shrunk. In stage 3, the router sends all requests to new services and the legacy system is retired. STAGE 1 requests Router all Legacy monolith STAGE 2 requests Router /orders everything else Orders new Legacy shrunk STAGE 3 requests Router all New services legacy retired

Anti-Corruption Layer

Trust boundary

One layer translates between the new model and the legacy one.

An anti-corruption layer between a new system and a legacy system The new system works with a domain model in its own terms. Its requests pass through the anti-corruption layer, which translates requests, translates responses, and maps codes and ids, to the legacy API or database, whose data uses legacy names such as CUST_ID and STAT equals A. Responses come back through the same layer. NEW SYSTEM Domain model in its own terms: Customer CustomerStatus.Active ANTI-CORRUPTION LAYER translate requests translate responses map codes and ids LEGACY SYSTEM Legacy API or DB CUST_ID STAT='A' Only the layer knows the legacy system's names, codes, and quirks.

Change Data Capture Pipeline

Flow

The legacy database's log feeds a new store that follows it.

Change data capture from a legacy database to a new database The legacy application writes to the legacy database, which remains the source of truth. A CDC connector such as Debezium reads the database's transaction log and emits change events to an event stream such as Kafka. A consumer transforms each event to the new model and writes it to the new database, which follows the legacy one. The legacy application is unchanged. Legacy application unchanged Legacy database source of truth writes CDC connector e.g. Debezium transaction log Event stream e.g. Kafka change events Transform to the new model New database follower

Found this useful? Share it:

Share on LinkedIn