Aggregates + Event Sourcing distilled

I have been following the excellent BTW podcast and thinking a lot about CQRS and Event Sourcing. Inspired by Greg Youngs lecture on Functional Programming with DDD I have tried to distill what is the minimal things I need to implement an Aggregate with Event Sourcing in Java. In this blog post I will focus on the command side of things. The purpose here is to explain Event Sourcing in a way that is easy to understand without any unnecessary overhead.

If you want to get directly to the example code it is available at GitHub.

A simple domain

To start we need a minimal domain that is simple to understand, but still interesting enough to be challanging. Udi Dahan has said many times that CQRS should only be used in a collaborative domain. Since I really enjoy developing games a really simple game that came to mind was rock-paper-scissors.

To keep it really simple the game only has two commands:

  • Player 1: Create game and make first move
  • Player 2: Make move

The business rules:

  • The players of a game must be different
  • When the second player has moved no more moves can be made
  • When the second player has moved either it is a tie or one of the players is declared winner

I will save queries and projections for another time.


To implement command processing I need the following pieces:

  • Commands which request that something should happen, ie some state change
  • Events which indicate that something has happened
  • Aggregates that handles Commands and generates Events based on the current state
  • Event store which stores all events that has happened
  • Application services that receives Commands and routes it to the appropriate aggregate

I want all updates to the aggregate to be consistent, which I implement by processing all commands sent to an aggregate serially using optimistic locking. This is consistent with Eric Evans view of aggregates. In fact, the extent of the aggregate is defined by the amount of data that is updated consistently. A Command is always sent to a single Aggregate.

I have the following commands:

  • CreateGameCommand(UUID gameId, String playerEmail, Move move)
  • MakeMoveCommand(UUID gameId, String playerEmail, Move move)

CreateGameCommand always generate these events:

  • GameCreatedEvent(UUID gameId, String playerEmail)
  • MoveDecidedEvent(UUID gameId, String playerEmail, Move move)

MakeMoveCommand also generate a MoveDecidedEvent and depending who wins one of the following events is generated:

  • GameWonEvent(UUID gameId, String winnerEmail, String loserEmail)
  • GameTiedEvent(UUID gameId)

By using multiple events to describe what happens (for example GameCreated + MoveDecided) I separate how the events get produced from what has happened. In this way I can change the workflow of the commands without changing the events that get generated. For example, I could introduce a new command that only creates a game without making a move.


Time for some code. Notice how each command is sent to a specific aggregate:

public interface Command {
    UUID aggregateId();

Commands are immutable data. I can of course add more validation of the input in the constructor. Notice how UUID is created by the one that is sending the command:

public class CreateGameCommand implements Command {
    public final UUID gameId;
    public final String playerEmail;
    public final Move move;

    public CreateGameCommand(UUID gameId, String playerEmail, Move move) {
        this.gameId = gameId;
        this.playerEmail = playerEmail;
        this.move = move;

    public UUID aggregateId() {
        return gameId;


This does not mean that the client is creating UUIDs. Instead it could be done in the REST API, for example like this using JAX-RS:

public Response createGame(Move move, @Context UriInfo uriInfo) {
    String playerEmail = getCurrentUserEmail();
    UUID gameId = UUID.randomUUID();
    sendCommand(new CreateGameCommand(gameId, playerEmail, move));
    return Response.created(pathToGame(gameId, uriInfo));

For events I currently have a simple marker interface:

public interface Event {


The events are just immutable data:

public class GameCreatedEvent implements Event {
    public final UUID gameId;
    public final String playerEmail;

    public GameCreatedEvent(UUID gameId, String playerEmail) {
        this.gameId = gameId;
        this.playerEmail = playerEmail;

The aggregate implement handlers for commands that generate events. Notice that no state is modified!

public List handle(CreateGameCommand c) {
    if (state != State.notStarted) throw new IllegalStateException(state.toString());
    return Arrays.asList(
            new GameCreatedEvent(c.gameId, c.playerEmail),
            new MoveDecidedEvent(c.gameId, c.playerEmail, c.move));

The aggregate implement handlers for events that modify state. Notice that no validation is done! The event has happened and the aggregate must simply accept this fact:

public void handle(GameCreatedEvent e) {
    state = State.created;
    creatorEmail = e.playerEmail;

For the command processing I have a very simple interface for the EventStore:

public interface EventStore {
    EventStream loadEventStream(UUID aggregateId);
    void store(UUID aggregateId, long version, List events);

An EventStream which is an immutable collection of events up until a specific version of an aggregate. The purpose of the version is to implement optimistic locking:

public interface EventStream extends Iterable {
    long version();

So far I have only implemented an in-memory event store.

The final piece of the puzzle is the Application Service that:

  • Load events for the event store
  • Instantiate a new aggregate
  • Applies all events on the aggregate
  • Sends the command to the aggregate
  • Store the new events
public void handle(Command command) throws Exception {
    EventStream eventStream = eventStore.loadEventStream(command.aggregateId());
    Object target = newAggregateInstance(command);
    for (Event event : eventStream) {
        handle(target, event);
    List events = handle(target, command);
    if (events != null && events.size() > 0) {, eventStream.version(), events);
    } else {
        // Command generated no events

The handle methods are invoked using reflection. There are couple of nice things to notice here:

  • The Application Service can easily handle retries if there is a ConcurrentModificationException (optimistic lock violation) or in fact any other exception
  • Command processing can easily be done asynchrously
  • Command processing can be distributed and run concurrently since all shared state is within the Event Store

There are of course problems as well. For example always loading and applying all events for an aggregate could be a performance problem. I will write about immutability and caching some other time!


That was all the pieces that are necesseary to implement Event Sourcing. Do you think it is a complex programming model? Well, lets have a look at the bulk of the business rules in the Game aggregate which are implemented when the opponent makes a move:

enum State {
    notStarted, created, completed;
private State state = State.notStarted;
private String creatorEmail;
private Move move;

public List handle(MakeMoveCommand c) {
    if (State.created != state) throw new IllegalStateException(state.toString());
    if (creatorEmail.equals(c.playerEmail)) throw new IllegalArgumentException("Player already in game");

    return Arrays.asList(
            new MoveDecidedEvent(c.gameId, c.playerEmail, c.move),
            makeEndGameEvent(c.gameId, c.playerEmail, c.move));

private Event makeEndGameEvent(UUID gameId, String opponentEmail, Move opponentMove) {
    if (move.defeats(opponentMove)) {
        return new GameWonEvent(gameId, creatorEmail, opponentEmail);
    } else if (opponentMove.defeats(move)) {
        return new GameWonEvent(gameId, opponentEmail, creatorEmail);
    } else {
        return new GameTiedEvent(gameId);

Event processing must never fail since the events have happened:

public void handle(MoveDecidedEvent e) {
    move = e.move;

public void handle(GameWonEvent e) {
    state = State.completed;

public void handle(GameTiedEvent e) {
    state = State.completed;

Notice the following things:

  • Because we are doing CQRS we only store state in the aggregate that we actually use for command procesing. For example, the opponent or winner is not stored.
  • The event processing is always trivial!
  • Implementing the command processing is not that difficult, only different. Instead of directly manipulating state we generate events.

Ok that was a long blog post! I’m planning to write more about projections, event storage, immutability and lots of other stuff. Let me know what you think so far!

This Post Has 15 Comments

  1. Fredrik Wendt

    Nice, not too long a post considering the amount of code you’ve included. Can’t wait for the rest of this series!

    Also, does this mean that you’ve actually started executing on the idea (mentioned during Software Passion) of providing an open source licensed reference implementation that any Java based project can simply pick up should they decide they need this?

    Anyway, thanks for sharing!

  2. Jan Kronquist

    All the code that I reference here is open source. I should probably add an appropriate license to the code!

    So far my goals are to explore event sourcing and to have a simple model that I can reason about, but hopefully it will also be easier to understand. The goal is not to have a production quality Event Store, but who knows what this will lead to!

    The clojure version is even more clean and I will use that to explore caching and snapshots. I hope that I manage to get that post out next week…. :-)

  3. Ramon Buckland

    Hi Jan,

    I have playing with the production ready Eventsourced Scala framework.

    There are a lot of things there and heaps to consider. What struck me was the simplicity of the libray. It is seen the best with both the examples, and documentation.

    downloading and running the “sample” application for invoices with uses Jersey and Jackson for JSON marshalling in and out will be very familiar for you.

    Im not a developer of it, just came across it and like what I have found so far.

  4. Vjeran Marcinko

    As far as I udnerstand, one difference between command and event in your example is that cmmand has tranasctional semantics, whereas events do not. Mening, if I use events to reconstruct the state of system on some other place, and if I have a case that one execution of one command generated 2 events, and that other consumer in the system consumed in some point in time only one of those 2 events, this consumer can have invalid state for that aggregate in that moment, right?

    1. Jan Kronquist

      The way I implement actual persistence is to make sure that all events generated by a single command is persisted together in a single transaction.

      Sending and receiving the messages is another story. You are absolutely correct that depending on the messaging infrastructure used messages may be lost between different systems. The solution is to implement at-least-once semantics and make sure to handle duplicates. You need to be aware that the other system will be in an inconsistent state until it has received all events.

      However, since events should have business meaning, the inconsistency will probably not be as bad as you might initially think. In some ways, the inconsistency will have some meaning at the business level. For example if you have received the final MoveEvent, but not yet the GameWonEvent, you can still do consistent statistics on the most popular moves and similar “business” operations. The inconsistency is manifested as the game appears to be still in progress.

  5. Vjeran Marcinko

    To add to my previous comment, it would somehow be best if one aggregate can publish only single event for each processed command, so the event would carry transactional semantics to any possible subscriber in the system, but in the same type, this event should be able to carry different information about the effects of command processing, such as different types of game ending in your example.

    1. Jan Kronquist

      Looks interesting!

  6. cristian e.

    How would you ensure this business invariant: “Live (started) Games must have Unique Title”?

    1. Jan Kronquist

      In this simplified example the CreateGameCommand both creates the game and make the first move. In this case you can simply add whatever validation you want in the CreateGameCommand constructor. However, you can also add checks in the command handlers similar to how I make sure that the game is not started twice:

      public List handle(CreateGameCommand c) {
      if (state != State.notStarted) throw new IllegalStateException(state.toString());
      // add whatever you like here!

Leave a Reply