When working with DDD we’ll face for sure problems getting data from another bounded context. Since we want them to be as less coupled as possible we’ll deal with complex situations here.
Let’s review the options we have taking as example a
Sales bounded context wanting to get user data from
Users bounded context.
This is the first option we’ll probably think about. It’s easy to implement since we just need to expose some user data through an internal endpoint which can be called by the
Sales bounded context.
The good things
Since will be a synchronous call it makes all the flow even easier, we call
Users BC and we get the data we need to do any action, for example to store a sell with the required data.
Also, since we’ll be going directly to the source of true for users data we’ll get always the very last data.
The bad things
In the other hand this will couple our two bounded contexts in a way that if
Users BC is down we can’t get any user data.
It’s true that we can use some kind of cache to minimize the outage for example if we store the user data we got for X time. This will also force us to deal with stale data, maybe we’ll want to purge that cache when a user updates their info… as we see this will start to get complex.
If the traffic of our
Sales BC increases a lot we’ll be adding load to the
Users BC, so these two bounded contexts will be somehow tied.
Data projections are a way to have a representation of a data coming outside of our bonded context in a way that it´s easy and very accessible.
For example if in sales we need the user data to deal with our clients we could create a new
clients projection that will be populated every time
Users bounded context publish a
UserCreated domain event. In the same way we’ll update our projection when
UserUpdated domain event is published, and we’d remove them when we receive
The good things
This solution it’s ideal for systems where reliability is key. Since if
Users BC is down somehow we’ll still be able to get our clients data from the projection we have stored locally in
Also, this will improve the performance of our system since getting clients data will be much faster since it will require just a query in some DB optimized to do that.
The bad things
When we start the projection will be empty forcing us to populate it somehow. One solution would be sending all the user related events to the projector in
Sales BC. In that way we’d get all the clients there. This might be a complex process or even impossible taking into account old events version or if we don’t have a proper event store with all the historic of events.
Since the projectors will be asynchronous processes we’ll lead with eventual consistency. We have to be sure that we can deal with it handling for example retries in case we receive the sell before getting the
An hybrid solution would be having a projection but without being populated with the very initial events. So if we try to get a user data of an existing one in the projection we’ll do a HTTP request to
Users BC and we’ll create that client in the projection so the next time we don’t need to do it again.
At some point we’ll have the projection full enough to have as less HTTP calls as possible.