Skip to content

Command Handlers

When a user sends a command, the system needs to decide what to do with it. That's the job of a command handler.

A command handler is responsible for:

  • Taking in a command
  • Loading the current state of the domain object it applies to
  • Running business logic and validations
  • Producing one or more events

In other words:

Command in → domain logic → events out

In Our Library

Let's say a member sends a BorrowBook command.

The command handler will:

  1. Load the current loan status of the requested copy
  2. Check if the copy is available
  3. Check if the member is allowed to borrow more books
  4. If everything checks out, emit a BookBorrowed event

The logic in this step belongs to the domain – it enforces the rules and conditions that matter to the library.

Stateless Input, Stateful Decision

At first glance, a command looks like just a function call. But it's not stateless. The decision about what events to produce depends on the current state.

That state is typically reconstructed by replaying past events – which makes the command handler part of the write model in Event Sourcing.

Business Logic Lives Here

Validations like "you can't borrow more than 5 books" or "you can't extend a loan that has already expired" do not belong in the UI or in a general-purpose service layer.

They live here – in the domain logic – where decisions are made, and events represent the outcome.

Next up: Now that we have events, where do we put them? See Producing Events.