Search Knowledge

© 2026 LIBREUNI PROJECT

Software Architecture / Distributed Design

Distributed Topologies & Service Decomposition

Distributed Topologies & Service Decomposition

Distributed architecture is a tool for independence, scale, isolation, and organizational fit. Fowler and Lewis emphasize independently deployable services organized around business capability; cloud architecture guidance adds the runtime cost: latency, partial failure, contract drift, debugging complexity, deployment coordination, and data consistency. Senior architects therefore ask which parts of the system need independent change, scaling, failure handling, or ownership badly enough to justify distribution.

Service decomposition begins with boundaries, not endpoints. A service should own a business capability, the data needed to enforce its invariants, and the operational responsibility for its runtime behavior. If a service cannot be deployed, observed, secured, and evolved independently, it may be a distributed module rather than a true service.

Code
left to right direction
rectangle "Decomposition Forces" as Forces
rectangle "Business Capability" as Capability
rectangle "Data Ownership" as Data
rectangle "Team Ownership" as Team
rectangle "Operational Independence" as Ops
rectangle "Service Candidate" as Service

Forces --> Capability
Forces --> Data
Forces --> Team
Forces --> Ops
Capability --> Service
Data --> Service
Team --> Service
Ops --> Service
Decomposition ForcesBusiness CapabilityData OwnershipTeam OwnershipOperational IndependenceService Candidate

Topology Choices

Distributed systems have topology. A request-driven topology routes synchronous calls through services. An event-driven topology publishes facts to a broker or log. A workflow topology uses orchestration or choreography to coordinate long-running business processes. A backend-for-frontend topology gives each user experience a tailored API. A mesh or gateway topology centralizes some cross-cutting routing and security behavior.

Each topology changes failure modes. A synchronous chain creates direct latency coupling: if inventory is slow, checkout may be slow. An event-driven topology reduces immediate coupling but creates eventual consistency and replay concerns. A workflow orchestrator clarifies process state but can become a central dependency. A gateway simplifies clients but can accumulate business logic if ownership is weak.

Code
left to right direction
actor "Client" as Client
rectangle "API Gateway" as Gateway
rectangle "Checkout Service" as Checkout
rectangle "Inventory Service" as Inventory
rectangle "Payment Service" as Payment
queue "Event Broker" as Broker
rectangle "Fulfillment Service" as Fulfillment

Client --> Gateway
Gateway --> Checkout : command
Checkout --> Inventory : reserve
Checkout --> Payment : authorize
Checkout --> Broker : OrderAccepted
Broker --> Fulfillment : start shipment
ClientAPI GatewayCheckout ServiceInventory ServicePayment ServiceEvent BrokerFulfillment ServicecommandreserveauthorizeOrderAcceptedstart shipment

Service Size and Responsibility

Service size is less important than service coherence. A small service with unclear ownership is worse than a larger service with a stable domain boundary. Services should be split when their reasons to change diverge, their scaling needs differ, their data ownership is independent, or separate teams need separate release cadence. They should not be split merely because classes feel large.

A common decomposition error is entity services: CustomerService, OrderService, ProductService, InvoiceService, each wrapping database tables and forcing business workflows to hop across network boundaries. Capability services are stronger: Checkout, Subscription Management, Claims Processing, Fraud Decisioning, Fulfillment Planning. Capability boundaries contain behavior, not just nouns.

Code
left to right direction
rectangle "Entity Service Trap" as Trap {
rectangle "Customer Service" as Customer
rectangle "Order Service" as Order
rectangle "Product Service" as Product
rectangle "Invoice Service" as Invoice
}
rectangle "Capability Boundary" as Capability {
rectangle "Checkout" as Checkout
rectangle "Subscription Management" as Subscription
rectangle "Fraud Decisioning" as Fraud
}
Customer -[#FF5555,dashed]-> Order : chatty workflow
Order -[#FF5555,dashed]-> Product : chatty workflow
Order -[#FF5555,dashed]-> Invoice : chatty workflow
Checkout --> Fraud : decision contract
Checkout --> Subscription : customer entitlement
Entity Service TrapCapability BoundaryCustomer ServiceOrder ServiceProduct ServiceInvoice ServiceCheckoutSubscription ManagementFraud Decisioningchatty workflowchatty workflowchatty workflowdecision contractcustomer entitlement

Coordination Models

Long-running workflows are unavoidable in distributed systems. Payment authorization, inventory reservation, shipment creation, invoicing, notification, and fraud review cannot always happen in one transaction. Coordination can be orchestrated by a workflow component or choreographed through events.

Orchestration makes process state explicit and easier to inspect. It can also centralize too much business knowledge. Choreography keeps services autonomous and extensible. It can also make the overall process difficult to understand unless events, tracing, and ownership are strong. The mature choice is not ideological. It depends on process criticality, need for visibility, number of participants, compensation complexity, and who owns the end-to-end outcome.

Code
left to right direction
rectangle "Order Workflow Orchestrator" as Orchestrator
rectangle "Payment" as Payment
rectangle "Inventory" as Inventory
rectangle "Fulfillment" as Fulfillment
rectangle "Notification" as Notification
database "Workflow State" as State

Orchestrator --> Payment : authorize
Orchestrator --> Inventory : reserve
Orchestrator --> Fulfillment : create shipment
Orchestrator --> Notification : send receipt
Orchestrator --> State : record step and compensation
Order Workflow OrchestratorPaymentInventoryFulfillmentNotificationWorkflow Stateauthorizereservecreate shipmentsend receiptrecord step and compensation

Operational Readiness

Every new service creates an operational surface: deployments, alerts, dashboards, logs, traces, secrets, certificates, dependency health, scaling policy, cost attribution, and incident ownership. If the platform does not make these cheap, service decomposition becomes organizational debt. A senior architecture proposal includes the operating model, not just the runtime boxes.

Service count should grow with platform maturity. Early decomposition can be useful for strong boundaries, but the organization must be able to operate the result. A team that cannot reliably answer “which service is failing, who owns it, and what changed?” should slow down distribution until observability and ownership are improved.

Code
rectangle "Service Readiness Checklist" as Checklist {
rectangle "Owner and on-call path" as Owner
rectangle "Deployment pipeline" as Deploy
rectangle "Dashboards and alerts" as Observe
rectangle "Contract versioning" as Contract
rectangle "Data ownership" as Data
rectangle "Runbook and rollback" as Runbook
}
Owner --> Deploy
Deploy --> Observe
Observe --> Contract
Contract --> Data
Data --> Runbook
Service Readiness ChecklistOwner and on-call pathDeployment pipelineDashboards and alertsContract versioningData ownershipRunbook and rollback

Practice

Choose a proposed service split and argue both sides. First, list the independence the split would create: deployment, scaling, ownership, security, or failure isolation. Then list the distribution costs: latency, consistency, observability, versioning, and operational burden. Decide whether to split now, create an internal module first, or delay until a specific trigger appears.

References & Further Reading