2PC vs Saga: Atomic Commit vs Compensating Transactions

Overview Both patterns coordinate a transaction that spans multiple services or databases, but they resolve the coordination problem in opposite ways. 2PC locks every participant until a coordinator confirms all can commit, guaranteeing atomicity at the cost of blocking; Saga lets each step commit immediately and unwinds failures afterward with compensating actions, trading strict atomicity for availability and throughput. Comparison Diagram 2PCSagaCoordinatorP1P2P3prepare / vote / commitlockedlockedlockedall-or-nothing, blocking until ackT1T2T3local commit, local commitcompensatecompensateindependent commits, compensating rollbacks Comparison Table Aspect 2PC Saga Initiation Coordinator sends a prepare request to all participants at once First service runs its local transaction and triggers the next step Commit decision Coordinator waits for every vote, then issues a single atomic commit or abort No central decision; each step commits independently as it finishes Resource locking Participants hold locks from prepare until the commit acknowledgment arrives No cross-step locks; each local transaction commits and releases immediately Failure handling Coordinator aborts and tells all participants to roll back the uncommitted work Already-committed steps are undone via explicit compensating transactions Atomicity guarantee True all-or-nothing atomicity across every participant No real atomicity; intermediate states are visible until compensations finish Coordination dependency Single coordinator is a synchronous, blocking point of failure Runs via choreography or a lightweight orchestrator that doesn’t hold locks Latency and throughput Higher latency and lower throughput from synchronous cross-service locking Lower per-step latency and higher throughput since nothing blocks across services Implementation effort Relies on XA-compliant resources and a transaction manager Requires custom compensating logic and step/state tracking per operation Key Differences 2PC provides true atomicity across services, while Saga only approximates it through compensations after the fact 2PC holds locks on every participant until the coordinator commits; Saga commits each step locally with no cross-service locking Saga failures require explicit compensating transactions; 2PC failures simply abort the still-uncommitted transaction 2PC depends on a synchronous coordinator that all participants must trust and wait on; Saga can run via choreography or a non-blocking orchestrator 2PC trades throughput for consistency, while Saga trades strict consistency for availability at scale When to Use Each 2PC ...

September 6, 2026 · 3 min · 470 words · jeonck

Choreography vs Orchestration: Who Drives the Workflow

Overview Both patterns coordinate a multi-step business process across independent services, but they differ in where the coordination logic lives. In choreography, each service reacts to events and decides its own next move with no central brain; in orchestration, a dedicated controller tells every service what to do and in what order. Comparison Diagram ChoreographyOrchestrationOrder SvcPayment SvcShipping SvceventeventeventOrchestratorPayment SvcOrder SvcShipping Svcno central controllercommands out, responses back Comparison Table Aspect Choreography Orchestration Trigger Any service publishes an event when something happens A client or event calls the orchestrator to start the process Coordination logic Distributed across each service’s event handlers Centralized in one orchestrator component Communication style Asynchronous events broadcast to whoever is listening Explicit commands and replies directed at specific services Step sequencing Emergent from chained event subscriptions Explicitly defined as a workflow or state machine Failure handling Each service listens for failure events and compensates locally Orchestrator detects failure and drives compensating transactions Adding a new step Add a listener; no existing service needs to change Update the orchestrator’s workflow definition Observability Hard to see the full process; requires distributed tracing Process state is visible in one place, easy to audit Coupling Low coupling between services, higher coupling to event schema Services decoupled from each other, but coupled to the orchestrator Key Differences Choreography spreads decision-making across services via events; orchestration centralizes it in a single controller. Choreography scales extensibility easily but makes the overall process hard to trace. Orchestration makes the workflow explicit and easy to audit, at the cost of a single point of coordination. Compensation logic lives in each service under choreography, but is driven centrally under orchestration. Orchestration introduces a dependency on the orchestrator itself as new coupling, even as it decouples the services from each other. When to Use Each Choreography ...

September 6, 2026 · 2 min · 413 words · jeonck

Shared Database vs Database Per Service: Data Ownership in Microservices

Overview This compares two data architecture patterns for microservices: a shared database where multiple services read and write the same schema, versus database per service where each service owns an isolated data store. The choice determines how tightly services are coupled, how transactions and queries span service boundaries, and how independently teams can deploy and scale. Comparison Diagram Shared DatabaseDatabase Per ServiceService AService BService CSharedDBService ADB AService BDB BService CDB CSingle point of coupling & contentionIsolated data, independent scaling Comparison Table Aspect Shared Database Database Per Service Schema ownership One schema shared and often co-owned by multiple teams Each service exclusively owns and evolves its own schema Write path Any service can write directly to shared tables Writes go only through the owning service’s API Cross-service queries Simple SQL joins across tables in one database Requires API calls, data replication, or an aggregation layer Distributed transactions Native ACID transactions across affected tables Needs sagas or eventual consistency to span services Schema migrations Any change risks breaking other services using the table Migrations are local and safe to run independently Independent scaling Database becomes a shared bottleneck under load Each store can be scaled or tuned to its own service’s needs Technology choice All services locked into one database engine Each service can pick the best-fit database technology Failure isolation A database outage or lock contention affects every service An outage is contained to the owning service’s data Key Differences Shared database allows cheap cross-table joins but couples every consuming service to one schema Database per service enforces service autonomy at the cost of needing sagas for cross-service transactions Schema changes in a shared database require coordinating multiple teams, while per-service schemas change independently A shared database creates a single failure domain; per-service databases contain outages to one service Polyglot persistence — choosing different database engines per need — is only possible with database per service When to Use Each Shared Database ...

September 6, 2026 · 3 min · 445 words · jeonck

Monolith vs Microservices: One Deployable vs Many

Overview A monolith packages an application’s entire codebase and functionality into a single deployable unit running as one process, while microservices split that same functionality into independently deployable services that communicate over a network. The choice shapes how teams build, deploy, scale, and recover from failures, so it matters far beyond just code organization. Comparison Diagram MonolithAuthOrdersInventoryPaymentsSingle processSingle deployMicroservicesAPI GatewayAuthOrdersInventoryPaymentsseparate databasesIndependent servicesIndependent deploys Comparison Table Aspect Monolith Microservices Codebase structure Single repository, one shared codebase for all functionality Multiple repositories, one per service with its own codebase Deployment unit Whole application built and shipped as one artifact Each service built, versioned, and shipped independently Inter-module communication In-process function calls within the same runtime Network calls via HTTP, gRPC, or messaging between services Data storage Typically one shared database for the whole app Each service usually owns its own database or schema Scaling Scale the entire application even if only one part is hot Scale only the specific services that need more capacity Fault isolation A crash or memory leak in one module can take down the app A failing service degrades its own function without necessarily crashing others Technology stack One language and framework across the whole application Each service can use the language/framework best suited to it Team ownership and releases One team or a coordinated release train ships the whole app together Independent teams own and release their services on their own schedules Key Differences A monolith runs as a single process, while microservices are distributed processes talking over the network Microservices trade in-process call reliability for network latency and partial failure handling Independent deployability lets microservices teams ship on separate release cadences, which a monolith can’t offer Splitting services adds real operational overhead — service discovery, monitoring, and distributed tracing Data ownership per service enables polyglot persistence but sacrifices easy cross-entity transactions When to Use Each Monolith ...

September 6, 2026 · 2 min · 425 words · jeonck

SOA vs Microservices: Enterprise Integration vs Independent Deployability

Overview SOA and microservices are both approaches to composing systems from independently callable services, but they differ sharply in scope and philosophy. SOA centralizes communication and governance through an enterprise service bus to integrate large, often legacy systems, while microservices decentralize communication, data, and deployment into small, independently shippable units. The distinction matters because it drives very different tooling, team structures, and failure characteristics. Comparison Diagram SOAMicroservicesS1S2S3S4ESBShared DBCentral bus + shared dataM1M2M3M4dbdbdbdbDirect calls, DB per service Comparison Table Aspect SOA Microservices Communication mechanism Services talk through a central Enterprise Service Bus using protocols like SOAP/WS-* Services talk directly via lightweight REST/gRPC calls or message brokers, no mandatory central bus Service granularity Coarse-grained, often modeling whole business processes Fine-grained, each service owns a single business capability Data ownership Services frequently share a common database or canonical data model Each service owns and manages its own private database Deployment unit Services often share application servers or deployment packages Each service is deployed and scaled independently, typically in its own container Technology stack Standardized enterprise-wide on common platforms and protocols Polyglot — each team chooses its own language, framework, and datastore Fault isolation The ESB is a potential single point of failure affecting many services Failures are isolated to individual services, limiting blast radius Governance & teams Centralized architecture review board and IT governance Decentralized ownership by small, autonomous teams per service Typical origin Emerged from large-scale enterprise integration needs in the 2000s Emerged from cloud-native, DevOps-driven practices in the 2010s Key Differences SOA centralizes routing and transformation logic in an ESB, while microservices push that logic into the endpoints themselves. Microservices mandate database per service, whereas SOA services commonly share a data layer. SOA favors reusable coarse-grained services across the enterprise; microservices favor small, single-purpose services. Microservices deploy and scale via independent containers, while SOA services often share application servers. SOA relies on heavyweight standards like SOAP/WS-*; microservices typically use lightweight REST or gRPC. When to Use Each SOA ...

August 4, 2026 · 3 min · 438 words · jeonck

Shared Database vs Database per Service: Data Ownership in Microservices

Overview A shared database lets multiple services read and write the same tables through one common schema, while database per service gives each service its own private data store that only it can touch directly. The choice determines how tightly services are coupled at the data layer, how independently teams can deploy, and how much work cross-service queries and transactions require. Comparison Diagram Shared DatabaseDatabase per ServiceService AService BService CShared DBone schema, every service reads/writes it directlyService XService YService ZDB XDB YDB Zeach service owns a private schema, accessed only via its API Comparison Table Aspect Shared Database Database per Service Data ownership No single owner — all services see and can modify the same tables Each service exclusively owns its schema; no one else can touch it directly Access path Services query the database directly, often with raw SQL against shared tables Other services only get data through the owning service’s API or published events Cross-service transactions Native ACID transactions and joins span all the data in one commit No shared transaction; consistency across services needs sagas or eventual consistency Cross-service queries Simple SQL joins pull data from any table in one query Requires API composition, data replication, or a separate CQRS read model Schema changes A column or table change can silently break unrelated services Schema changes are internal; only the public API contract must stay stable Technology choice All services are locked into one database engine and schema Each service can pick the storage engine that fits its data (polyglot persistence) Failure isolation A database outage or lock contention affects every service at once An outage in one service’s database doesn’t directly take down the others Operational overhead One database to provision, back up, and tune N databases to provision, monitor, back up, and scale independently Key Differences Shared database gives every service direct access to the same tables, so a change in one place can silently break another service’s queries — a form of tight coupling. Database per service forces all cross-service data access through an API, giving each service true encapsulation of its data. Cross-entity consistency is a native ACID transaction in a shared database, but needs a saga pattern or eventual consistency once data is split per service. Reporting and ad-hoc joins are trivial with a shared database’s SQL, while database per service usually needs a separate CQRS read model to answer cross-service queries. Database per service allows polyglot persistence — each service picks its own database engine — whereas shared database locks every service to one engine and schema. When to Use Each Shared Database ...

August 4, 2026 · 3 min · 573 words · jeonck

Orchestration vs Choreography: Coordinating Distributed Workflows

Overview Orchestration and choreography are two ways to coordinate multiple services in a distributed system or workflow. Orchestration relies on a central controller that explicitly directs each step, while choreography lets services independently respond to event reactions with no single component in charge. The choice shapes coupling, visibility, and how easily the workflow evolves over time. Comparison Diagram OrchestrationChoreographyOrchestratorService AService BService CCentral controller directs each stepService XService YService ZeventeventeventServices react to each other's events Comparison Table Aspect Orchestration Choreography Control flow A central orchestrator explicitly invokes and sequences each step Each service reacts to events independently; no component sequences the whole flow Coupling Services couple to the orchestrator’s contract, not to each other Services couple to shared event schemas rather than a controller Workflow knowledge Orchestrator holds the full picture; services only know their own task No single component knows the entire workflow, only its trigger and reaction Failure handling Retries and compensation logic live centrally in the orchestrator Compensation is distributed, with services reacting to failure events themselves Adding new steps Requires modifying the orchestrator to include the new call A new service just subscribes to existing events with no central change Observability Single place to trace and inspect current workflow state Requires aggregating distributed logs and traces across services Failure/scaling risk Orchestrator can become a bottleneck or single point of failure Overall flow becomes hard to see, risking uncoordinated ’event sprawl' Typical tooling BPMN engines, AWS Step Functions, Temporal, Camunda Message brokers and event buses like Kafka, SNS/SQS, domain events Key Differences Orchestration uses a central controller; choreography relies on services reacting to events Orchestration couples services to the controller; choreography couples them to event contracts Extending orchestration means updating the orchestrator; extending choreography just means subscribing to events Orchestration gives centralized visibility; choreography requires distributed tracing to see the full flow Orchestration risks a bottleneck at the controller; choreography risks workflow sprawl across services When to Use Each Orchestration ...

August 4, 2026 · 3 min · 433 words · jeonck

Monolith vs Microservices: Architecture Comparison

Overview Monolithic architecture packages an entire application as a single deployable unit, while microservices architecture splits it into independently deployable distributed services. The choice shapes everything from how teams organize their work to how failures propagate and how the system scales under load. Comparison Diagram Monolith Microservices UI Layer Business Logic Data Access Shared DB single deployable unit API Gateway Orders Users Payments Inventory db db db db independent, own datastores Comparison Table Aspect Monolithic Architecture Microservices Architecture Deployment unit Single deployable artifact containing all modules Multiple independently deployable services Inter-component communication In-process function calls Network calls (REST, gRPC, or messaging) Data storage Typically one shared database Each service owns and manages its own database Scaling approach Scale the entire application as one unit Scale individual services independently based on load Fault isolation A bug or crash can bring down the whole application Failures can be isolated to a single service when designed well Release and deployment process Single build/deploy pipeline with coordinated releases Independent CI/CD pipeline per service, deployed on its own schedule Technology stack flexibility One language and framework for the entire app Polyglot — each service can pick its own stack Operational overhead Low — one application to host and monitor High — requires service discovery, orchestration, and distributed tracing Key Differences Monolith code runs as a single process; microservices communicate as independent processes over the network. A monolith centers on one shared database, while microservices decentralize data ownership per service. Microservices allow granular scaling of just the components under load, unlike a monolith that scales as a whole. Splitting into services buys better fault containment but introduces real operational complexity. Well-designed microservices offer stronger fault isolation than a monolith, where one bug can crash everything. When to Use Each Monolithic Architecture ...

August 4, 2026 · 2 min · 425 words · jeonck

Sidecar Pattern vs Ambassador Pattern: General-Purpose Helper vs Network Proxy

Overview The Sidecar Pattern is the general technique of running a helper container alongside your app in the same pod to add any cross-cutting capability — logging, metrics, config sync, or a mesh proxy. The Ambassador Pattern is a specific flavor of that sidecar dedicated to one job: sitting between the app and the network, so the app talks to localhost while the ambassador handles the real, often messy, connection to an external service. ...

August 3, 2026 · 3 min · 504 words · jeonck

Service Mesh vs API Gateway: North-South vs East-West Traffic

Overview An API gateway sits at the edge of your system, managing traffic between external clients and your services. A service mesh operates inside the cluster, managing traffic between services themselves. Confusing the two leads teams to either duplicate cross-cutting concerns or push edge-only features into infrastructure that was never designed for public-facing traffic. Comparison Diagram API GatewayService MeshClientAPI GatewayauthN · rate limitrouting · transformclusterService AService BService Csidecar proxymTLS · retriesnorth–south: client-to-serviceeast–west: service-to-service Comparison Table Aspect API Gateway Service Mesh Traffic direction North-south: external clients entering the system East-west: internal service-to-service calls Deployment topology Centralized cluster of edge instances fronting all traffic Sidecar proxy injected alongside every service instance Primary concerns AuthN/authZ, rate limiting, request/response transformation, API versioning mTLS, load balancing, retries, circuit breaking between services Routing basis Public API path, host, or version mapped to a backend service Service identity and destination within the internal network Observability scope Per-endpoint metrics: request volume, latency, errors by client Full service dependency graph: per-hop latency and error rates Failure containment Blocks or throttles bad traffic before it reaches any backend Isolates failures at individual hops so one bad service doesn’t cascade Operational overhead Few instances to scale and configure centrally One proxy per workload, plus a control plane to manage them all Key Differences An API gateway is the single entry point clients hit; a service mesh has no single entry point, it’s woven through every service. Gateways enforce policy once at the edge; meshes enforce policy per sidecar on every call. Gateways typically run as a small number of centralized instances; meshes scale linearly with your service count. Meshes give you mTLS and retries between internal services, something a gateway never sees because that traffic never reaches it. Many production systems run both together, not as alternatives, since they solve problems at different layers. When to Use Each API Gateway ...

August 3, 2026 · 2 min · 424 words · jeonck