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.