Skip to content

Decompose by Business Capability

You are about to carve a system into services and you need a first principle to guide the cuts. You want boundaries that will still make sense in three years, owned by teams that can ship without constant cross-team negotiation. The instinct of many engineers is to slice by technology — a service for the API, a service for the workflow engine, a service for the reporting jobs — because that is how the codebase is already arranged in their heads.

Technology changes far faster than what the business actually does. Frameworks come and go, data stores get swapped, an API moves from REST to gRPC — but a retailer still takes orders, charges customers, and ships goods. If you draw service boundaries around today’s technology, every one of those technology shifts forces a re-decomposition. Worse, slicing by layer guarantees that the simplest business change — say, adding a discount rule — touches the web service, the logic service, and the data service at once. The lines you drew do not match the lines along which the system actually changes.

So the forces are: you want boundaries that are stable, that produce high cohesion (everything that changes together lives together) and low coupling (services rarely have to change in lockstep), and that map cleanly onto how the organization is structured.

A business capability is something an organization does in order to generate value — it answers “what does this business do?”, deliberately ignoring how it is currently done. A capability is stable precisely because it is defined by purpose, not implementation. For an e-commerce company the capabilities might include Order Management, Product Catalog, Inventory, Billing, Shipping, and Customer Accounts.

The pattern is to define one service per business capability (or per closely related group of capabilities). You identify the capabilities by studying the organization: its purpose, its structure, and the value streams it operates. Capabilities are often hierarchical — Order Management might contain Order Capture, Order Fulfilment, and Returns — which gives you a natural lever for choosing how coarse or fine to make each service.

Because capabilities reflect what the business does rather than how, the resulting boundaries are durable. You can rewrite a service’s internals, swap its database, or change its API and the boundary still holds, because the capability it represents has not changed.

flowchart LR
  subgraph Org[Business capabilities]
    direction TB
    OM[Order Management]
    PC[Product Catalog]
    INV[Inventory]
    BIL[Billing]
    SHP[Shipping]
    ACC[Customer Accounts]
  end
  OM --> SOM[Order Service]
  PC --> SPC[Catalog Service]
  INV --> SINV[Inventory Service]
  BIL --> SBIL[Billing Service]
  SHP --> SSHP[Shipping Service]
  ACC --> SACC[Account Service]
Each business capability becomes a service; the boundary follows what the business does, not how it is built

Capabilities are conceptual, but they show up concretely as the modules you organize code and ownership around. The snippet below is not an algorithm — it simply records the capability map as a small manifest, the kind of artefact a team keeps to make the boundaries explicit and reviewable.

type Capability = {
name: string;
service: string;
// Sub-capabilities help decide how coarse the service should be.
subCapabilities: string[];
};
const capabilityMap: Capability[] = [
{ name: 'Order Management', service: 'order-service',
subCapabilities: ['Order Capture', 'Order Fulfilment', 'Returns'] },
{ name: 'Billing', service: 'billing-service',
subCapabilities: ['Invoicing', 'Payments', 'Refunds'] },
{ name: 'Shipping', service: 'shipping-service',
subCapabilities: ['Carrier Selection', 'Tracking'] },
];

What you gain:

  • Stable boundaries. Capabilities change far more slowly than technology, so services drawn around them rarely need to be re-cut. A rewrite stays inside one service.
  • High cohesion, low coupling. Everything needed to perform a capability lives in one place, so most business changes land in a single service rather than rippling across several.
  • A clean map to the organization. Capabilities tend to line up with how the business already thinks about itself, which makes ownership and accountability easy to assign.

What it costs you:

  • You must actually understand the business. This is the hard part. Identifying capabilities well requires domain knowledge and conversations with people outside engineering; a superficial map produces superficial boundaries.
  • Granularity is a judgement call. Capabilities nest, so deciding whether Order Capture and Returns are one service or two is not mechanical — get it too coarse and you rebuild a mini-monolith, too fine and you drown in inter-service chatter.
  • It does not, by itself, give you a shared model. Two services may use the word “order” to mean subtly different things; capability decomposition stops short of resolving that, which is exactly where decomposing by subdomain picks up.
What is a business capability?
Why are boundaries drawn around business capabilities considered stable?
Which is a genuine drawback of decomposing by business capability?