Search code examples
domain-driven-designcqrsevent-sourcing

Event validation


We are considering implementing CQRS pattern at work and have a couple of questions about validation.

Let's say we have 3 aggregate roots:

  • User
  • Business
  • UserToBusinessRelationship

When user signs up the events sent would be:

UserCreated
BusinessCreated
UserAddedToBusiness

Events need to be validated, for example to create a link between a user and a business both user and business should be created.

I see two approaches.

  1. Upfront validation: construct read model on the fly using last processed snapshot plus unprocessed events and use it for validation.

  2. Validation while processing: accept events/commands as-is and do the validation while processing events.

The first approach has immediate feedback but it requires creating a final read model just for validation. Second is simpler, but gives no feedback to consumer that something went wrong.

I was thinking about something like this: when you emit an event, you get back an id which you can later use to query the status of an event. If event processing was successful you'd get 'OK', otherwise you'd get an error telling what went wrong.

Is it a valid approach or an overkill? How would a consumer know that event has been processed and the data is ready to be used?


Solution

  • Great question Leonti - You may find my blog post on validation in a CQRS system helpful. You can find the link to my post at the bottom of this answer.

    Just notice from the title that the emphasis in CQRS is to validate commands and not events.

    Why?

    Because a command can come from user input and shouldn't, therefore, be trusted. Events, on the other hand, are emitted from within the domain and can be trusted. There may be implementations of CQRS which involve events leaving the bounds of a system or receiving events which are not originated from within the system. In those edge cases, care should be applied.

    Another potential red flag is the way you have described your aggregates. It would appear to me (and I don't know your domain so can't be 100% sure) that they are more akin to tables in a database rather than aggregates. It's important not to let the way your persistence mechanism dictate your models.

    Getting back to your question more specifically.

    Broadly speaking there are 2 types of validation. Superficial and deep. Superficial is stuff like missing fields, valid email addresses etc. Deep is when a domain concept is at play. e.g. the weight of the cargo is required and a superficial validation but whether or not the cargo is appropriate for the carrier may be a domain concept.

    You may need to validate against the existence of things.e.g. Does a business or user exist. While this validation will more than likely require you to access the database, it is still superficial as it is unlikely to be an explicit domain concept.

    Anyway, I hope that helps.

    Note: please read the comment about this link Blogpost URL: https://danielwhittaker.me/2016/04/20/how-to-validate-commands-in-a-cqrs-application