Event Sourcing

Let's write some history

Quick introduction

Willem-Jan Zijderveld

  • @willemjanz
  • github.com/wjzijderveld




Event Sourcing and CQRS library for PHP


Event Sourcing

You are throwing away data!

State gets stored

A company has one or more connected accounts

A company has one or more enabled applications

An account has access to one or more applications

Complicated solutions to store and retrieve the data

Boss: Which accounts received access to application X in December?

We'll add a timestamp
and we will know

From that point in time

With CRUD you lose information

You only store the latest information

Revoking access to an application for an account

You could lose when the access was revoked

You could lose why it got revoked

You could lose for which application it was revoked

You wouldn't know anything anymore

Let's assume you have
a soft-delete in place

Boss: I want to know for which applications access got revoked more than once
in the last year

Keep track of revocations

account_id app_id datetime
75623 8 2015-01-01T00:00:00+0000
75623 8 2015-01-27T18:54:18+0000

Past revocations are gone

How does Event Sourcing help me with that?

Store your data in
a different way

Record what has changed

The resulting state becomes a natural effect


A serie of facts


Been there, done that

Single source of truth

  • One source to rule all state
  • The events cannot lie, it happened, deal with it

Your version control is event sourced

Sure thing, but how?

Well.. that is a complicated question

Event Sourcing + CQRS + DDD

That is a lot to cover in one evening

But each can be used on its own

Domain Driven Design

The business should understand our events

Aggregate root

Responsible for keeping a group of entities consistent

Something happened...
now what?

Record the change


A message to tell your application what happened


  • Identifier
  • Sequencenumber
  • Event
  • Timestamp
  • Metadata

Identifier + sequencenumber


It tells you WHAT happened

The name should be descriptive

Should contain everything

It should only depend on previous events

final class CompanyRegisteredEvent
  private $companyId;
  private $companyName;

  // constructor + getters


It tells you WHEN it happened


Descriptive, not structural

Apply the event



// Company
function applyCompanyRegisteredEvent(CompanyRegisteredEvent $event)
  $this->companyId = $event->getCompanyId();


// Company
function applyAccountConnectedEvent(AccountConnectedEvent $event)
  $this->accounts[$event->getAccountId()] = $event->getAccountId();


// Company
function applyAppEnabledEvent(AppEnabledEvent $event)
  $subscription = new Subscription($this->companyId, $event->getAppId());
  $this->subscriptions[$event->getAppId()] = $subscription;


// Company
public function getChildEntities()
  return $this->subscriptions;
// Subscription
function applyAccessGrantedToAppEvent(AccessGrantedToAppEvent $event)
  if ($this->appId !== $event->getAppId()) {

  $this->grantedAccounts[$event->getAccountId()] = $event->getAccountId();

From Controller
to CommandHandler

class CompanyController
  function createAction(Request $request)
    $this->commandBus->dispatch(new RegisterCompanyCommand(
      new CompanyId(Uuid::uuid4()),
      new CompanyName($request->request->get('companyName'))

From CommandHandler
to Aggregate

class CompanyCommandHandler
  function handleRegisterCompanyCommand(RegisterCompanyCommand $command)
    $company = Company::register(


From Aggregate to Event

class Company extends EventSourcedAggregateRoot
  public static function register(CompanyId $companyId, CompanyName $name)
    $company = new Company();
    $company->apply(new CompanyRegisteredEvent($companyId, $name));

    return $company;

  public function applyCompanyRegisteredEvent(/**/ $event)
    $this->companyId = $event->getCompanyId();

Scenario based testing

    new CompanyRegisteredEvent(new CompanyId(123))
  ->when(function ($company) {
    $company->enableApp(new AppId(42));
    new AppEnabledEvent(new AppId(42), new CompanyId(123))

How to create a list of companies

Creating read models

Listen to the events


class CompanyRegistration implements ReadModel
  private $companyId;
  private $companyName;
  private $registeredOn;

  public function __construct(
    CompanyId $companyId,
    CompanyName $companyName,
    DateTime $dateTime
  ) {
    // ..


class CompanyRegistrationProjector
  public function applyCompanyRegisteredEvent(
    CompanyRegisteredEvent $event,
    DomainMessage $domainMessage
  ) {
    $company = new CompanyRegistration(


Combine different read model repositories

Use the right tool for the right job

Another scenario test

class CompanyRegistrationProjectorTest
  public function it_creates_a_company_registration()
      ->when(new CompanyRegistered('123', 'Acme Inc.'), $dateTime)
      ->then([new CompanyRegistration('123', 'Acme Inc.', $dateTime)]);

Possibilities are endless

The ability to create multiple read models

  • List of company registrations
  • Graph of all connections between companies and accounts
  • Creating reports about the amount of revocations

Time travel is possible!

Use events you recorded to create a new report
multiple years after the fact

You made a mistake in a projection?

So what? Correct your projector and recreate your read model from your event stream






Freenode: #qandidate

More information

  • http://codebetter.com/gregyoung/2010/02/20/why-use-event-sourcing/
  • http://codebetter.com/gregyoung/2010/02/13/cqrs-and-event-sourcing/
  • http://martinfowler.com/eaaDev/EventSourcing.html
  • http://martinfowler.com/bliki/CQRS.html
  • http://www.axonframework.org/docs/2.3/domain-modeling.html
  • http://labs.qandidate.com/