Back to articles
DDDFebruary 12, 2026

Bounded contexts are a language boundary, not a folder structure

A folder named Billing next to a folder named Shipping looks like two bounded contexts. It isn't one until the word Order means something different in each.

In billing, an order is a debt: a set of line items with a price, waiting to be invoiced. In shipping, the same order is a set of physical items with a weight and a destination, waiting to be packed. Model both with one Order class shared across the codebase and you get a class with a weight field that billing never uses and a total field that shipping never reads - fields that exist because two different mental models were forced to share one shape.

The tell

You know a context boundary is missing when a class has fields, or methods, that only make sense to one team reading the code. Ubiquitous language is ubiquitous inside a context, not across all of them. Order is allowed to mean two different things in two different contexts, on purpose.

What the boundary actually is

A bounded context is not a package, a microservice, or a database schema - those are implementation choices you can make later. It's the boundary within which a term has exactly one meaning, agreed on by the people who use it. Draw it around a shared vocabulary, not around a technical layer.

The tradeoff: crossing a bounded context means translating, not reusing. An Order that enters the shipping context from billing arrives as a ShippableOrder, built by an anti-corruption layer, not passed through as-is. That's an extra class and an extra mapping step for something that used to be a free import. It's worth it the moment two teams start arguing about what a field named status should mean.