The question touches on two distinct but complementary aspects:
- the domain with domain models within bounded contexts. Several strategies are possible for context mapping, i.e. relating different models corresponding across the boundaries of each context.
- the architecture and the components that implement the domain models.
We could perfectly imagine different bounded contexts that end up being implemented in the same database. Moreover some parts of the bounded contexts could be aligned (e.g.
Product could be part of a shared kernel, or
Sales could be a conformist to
Catalogue slavishly taking over its
Product definition). In this case you wouldn't have a question.
But the bounded contexts could as well have a very different view on products, such as having different product ids and even different lifecycles as you described. Typically, an anticorruption layer in one domain could bridge the gaps between the different product worlds. If you'd still have an implementation in the same database, the anticoruption layer would probably contain a mapping table (e.g. SalesProductId + CatalogueProductId + status information to deal with the different lifecycles or some redundant data, that would stay if the catalogue product is deleted).
Finally, you could have a very different architecture, e.g. microservices per bounded context, with independent databases. This deployment perspective is orthogonal to the context design: you could still have a shared kernel or conformist, in which case you'd need to replicate some data across the services. Or you could manage domain specific products in each microservice, with an anticorruption layer for making the glue and enabling synchronisations between divergent models. The additional logic for synchronising the data is independent of the context boundaries; it's just that these would coincide with the boundaries between microservices. Typically, such synchronization would base itself on events (domain events, that can be translated by the anticorruption layer)