You did a great and an extensive analysis in your post, but this is the part I disagree with. Those four places may already seem like a lot, at least to people just getting started or people writing smaller systems. Adding a fifth place (possibly even 6th if you want to add specs, which I believe you should) is going to make things quite tedious. To be clear, I don’t think this is a bad approach, but I feel the effort only becomes worth it in larger codebases.
The gist of the tradeoff is expressed here:
Adding fifth place for making future refactors a little bit easier
You seem to argue we should overcomplicate the design today to make some possible future change easy. This seems like a classical case of YAGNI. Martin Fowler did a great treatment of the topicin this article. The gist of it is:
a) You’re betting on one of the many possible futures. Chances are slim that you’re right.
b) Even if you’re correct, a lot of effort will be spent maintaining an overly complex design before the future change is actually needed.
For more discussion of the topic I also recommend Is Design Dead by the same author.
To answer the original question - I believe that it’s fine for multiple contexts to use the same tables. In my view, Phoenix contexts are not DDD bounded contexts. Bounded contexts are used in much larger domains, and my impression is that people typically use different databases or at least completely different db tables. That’s a lot of ceremony, and you need to have a large enough use-case to justify it. My impression from the original post is that the domain is nowhere near as large to justify such ceremony. As usual, there’s no one size that fits all scenarios.
When it comes to Ecto schemas, I think that it’s fine to use them across contexts. Schema is part of the context interface (after all, we return schemas to Web), so I see no reason why one context shouldn’t use schemas from another one. TBH, I don’t really think that schemas are owned by a particular context anyway. They are context-level entities, but not necessarily tied to some particular context.
However, I do agree with this:
I wouldn’t put it so strongly, but I do agree that a case of two contexts updating the same schema is a likely design issue, for example that things which belong together are separated. Which leads me to the following question:
I’m not completely sure I understood the problem, so let me paraphrase it. Let’s say that we must support the following scenarios:
- A user can update their own profile
- An admin can update anyone’s profile
The way I’d model this is via a single function, e.g. Profile.update(user_id, updater_id, data_to_update). Both admin UI and user UI would invoke this functionality. The domain rules related to profile would be encoded in the single place. When you want to understand how a profile can be updated this would be the single source of truth.
This would also mean that I’d have no admin context. Admin UI is a UI concern, and UI is just a view of the domain, but it’s not the domain itself. Both UI and domain are driven by the current requirements, but that doesn’t mean that the domain should map exactly to the way UI is organized.






















