When first learning Domain Driven Design it is common to run into problems in data sharing. Domain Driven Design recommends that data is kept in silos, or Bounded Contexts, where only one BC is allowed access and if other Bounded Contexts need access to that data they must ask for it. This can lead to a multitude of API calls from one BC to the others to gather information necessary for a use case, thus leading to system slowdown and complication.
One Big App
The core problem here is treating all Bounded Contexts together as one big application, and each Bounded Context is only a piece. Think of each Bounded Context as an individual, standalone application that gets input from various places. Data input can be from a user, an external system not controlled by us, or an external system that is controlled by us (i.e. a different Bounded Context). When you get information from an external system you don’t control, like a user typing into a data entry form or customer data uploaded in a CSV file, you cache it locally for future use. That is exactly what we do among the Bounded Contexts.
Don’t Repeat Yourself
One concern that comes up when discussing caching is data duplication. A cardinal rule in programming is DRY, and data duplication is breaking the DRY rule in the database. However that is again treating the Bounded Contexts as parts of a larger system. Having 2 copies of a user’s last name in different Bounded Contexts is not a problem as long as only one of those Bounded Contexts is responsible for updating it.
By allowing each Bounded Context to cache data from other Bounded Contexts to make access more convenient and we avoid the problem of lengthy queries for data. However, we introduce another problem: stale data. We can minimize this stale data by having the BC responsible for the data publish events indicating when a particular piece of data has changed. Other Bounded Contexts subscribe to these messages and update their caches as necessary.
This does leave a small amount of time where data cached in other Bounded Contexts is stale. This is called Eventual Consistency and it’s something that we must embrace as developers in an online, cloud base, infinitely scalable world. The only way to avoid this slight delay (which should be fractions of a second) is to
- Abandon Bounded Contexts altogether and use a shared database
- Merge the two Contexts
- Go back to live API calls among the Bounded Contexts
- Wrap the data modification and all cache updates in a big transaction
Hopefully you see that all these solutions are worse than the original problem.
Limit Data Cached
One further note on caching and duplication of data. The Bounded Context responsible for maintaining the data should publish all data changes in its message so subscribers can access the data they need. Each subscribing Bounded Context should only cache the pieces of data that are important to it. If you find a subscribing Bounded Context is caching all fields of an Entity or Aggregate maintained by a different Bounded Context, you should examine how the Bounded Contexts are defined because there is probably a mixing of responsibilities.