In the previous articles of this series, we covered the network and security layers of the authentication service: PKCS#12, timing oracle, mTLS, CRL. Let's now dive into the application architecture. The service is built with CQRS + Event Sourcing, and two non-obvious patterns deserve an article.

The event-XOR-error invariant

In a well-disciplined CQRS/ES system, a command handler does exactly one thing: it emits an event OR returns an error. Never both. Never neither.

func (h *LoginHandler) Handle(cmd LoginCommand) ([]Event, error) {

user, err := h.repo.Load(cmd.UserID)