intermediate 1 min answer

A subscription-billing platform has an "invoice service" that generates invoices, sends dunning emails, computes tax, syncs to accounting systems and renders PDFs. Is that cohesive? How would you decide?

cohesionchargebeebillingboundarieschange-frequency
Show the full answer Hide the answer

The wrong test

The naive test is thematic: "these are all invoice things, so they belong together." Thematic grouping is the weakest form of cohesion and it produces modules that are large, jointly deployed, and changed for unrelated reasons.

The test that works

Do these things change for the same reason, at the same time, driven by the same stakeholder? Applied here:

Responsibility Changes because Cadence
Invoice generation Billing logic, proration rules Rarely, carefully
Tax computation Jurisdictional tax law Frequently, externally driven
Dunning emails Retention experiments Constantly
Accounting sync A third party's API changed Unpredictably
PDF rendering Branding, templates, localisation Cosmetically, often

Five different reasons and five different cadences. This is not one module; it is five things sharing a namespace. The practical symptom is that a copy change to a dunning email requires deploying the code that computes money, and that risk asymmetry is what makes the team slow and cautious about both.

Where the real boundary is

Invoice generation and proration are the cohesive core — they share invariants, they change together, and they are the part where correctness is expensive. Tax is a volatile external domain and belongs behind an anti-corruption layer. Dunning is a communication workflow driven by invoice events. Accounting sync is an integration. PDF rendering is a presentation concern that should not be able to fail a billing run.

The clue was in the failure mode, not the domain model. Ask what has to be deployed together and what has ever broken together, and the boundary usually announces itself.