1

An Aggregate Root should always have a unique ID within the bounded context. Typically the examples one finds use a GUID for this to ensure global uniqueness.

However consider a bounded context for a Chat. In this case I deem messages and chats as their own individual aggregate roots. One may consider Message an entity of Chat, however if messages are to grow without bounds, this is infeasible.

Therefore a Message would hold the reference to the Chat to which it belongs, by ID. In this case I would need a large enough message Id to ensure that it is unique w.r.t. all other messages independent of Chat.

I am wondering if it is bad practice to instead make a composite key for Message of the form (ChatId, MessageId). This would ensure uniqueness, and at the same time I do not need MessageId to be as large as mentioned above, thereby saving some space.

udnes99
  • 59

2 Answers2

2

Although a composite key is not a bad practice, I would recommend you to use a UUID.

Lets consider an UUID v4, for example, that is generated randomly:

The number of random version-4 UUIDs which need to be generated in order to have a 50% probability of at least one collision is 2.71 quintillion [...]

Source: Universally Unique Identifier - Collisions

So, even for a chat app, is really, really unlikely that a id collision will happen.

Thinking from the YAGNI perspective, I believe that, when you reach the point when you will need to worry about collision, you will already have the people and money to come up with a different solution, as your chat will be a very successful product at that point.

Useful resources:

Universally Unique Identifiers

Are UUIDs really unique?

Caconde
  • 208
1

You really need to decide:

  • Either Message is an independent aggregate root, and it has an independent unique Id,
  • Or Message belongs to the Chat aggregate, in which case it depends on Chat and is accessed via the aggregate root.

Using a composite key is in reality a mean to implement the latter. A composite key for Message that builds on Chat's Id would express a dependency on Chat. This would negate the claimed independence of Message and hence be inconsistent with your design.

More arguments: Suppose you'd go for independent aggregate roots and use a composite key: what would happen if you decide to delete a chat ?

  • Would you also delete the relevant messages? But wouldn't this be a symptom that they belong to the same unit of consistency and share a common invariant?
  • Would you keep the relevant messages? But how wouldn't this be inconsistent with your database schema?
Christophe
  • 81,699