Scout APM is PHP application performance monitoring designed for developers. With tracing logic that ties issues back to the line of code causing them, you can pinpoint n+1 queries, memory leaks, and other abnormalities in real time so you can knock them out and get back to building a great product. Start your free 14-day trial today and get the performance insight you need in less than 4 minutes.

laravel-event-sourcing v3 has been released

Original – by Freek Van der Herten – 3 minute read

Our spatie/laravel-event-sourcing package is probably the best starting point for event sourcing in Laravel. It has excellent docs, that explain event sourcing from scratch, support for aggregates, projectors, and much more! It's all beautifully integrated in Laravel.

Recently we released v3 of the package. In this blogpost I'd like to walk you through the changes.

This post will probably not make much sense to you if you don't know anything about event sourcing. To get up to speed, watch this introduction video first.

Improve performance by using snapshots

When an aggregate gets instantiate all events concerning that aggregate will be replayed on it first, so it has the right, current state. Typically, retrieving past events and replaying them is very fast, but if your aggregate needs a very large number of events to be replayed, this might take some time.

To solve this problem, we added snapshots to the package. A snapshot hold the state that an aggregate should have after a certain number of events have been replayed. By loading the aggregate you don't have to replay previous events anymore, and this improves performance.

You can create a new snapshot by calling the ->snapshot() method on your Aggregate.

$myAggregate = MyAggregate::retrieve($uuid);


This will create a new snapshot in the snapshots table. By default we store the values of all the private, protected and public properties on the aggregate at that point in time. This is the default implementation of the getState method that gets all those properties.

protected function getState(): array
    $class = new ReflectionClass($this);

    return collect($class->getProperties())
        ->mapWithKeys(function (ReflectionProperty $property) {
            return [$property->getName() => $this->{$property->getName()}];

If you don't want all those properties in your snapshot, just override the getState() and useState() methods on the aggregate and implement your own behaviour.

When you retrieve the aggregate the next time, it will find the snapshot, set its internal properties back to what they were at the time of the snapshot, and apply any new events starting from the snapshot.

This uses the snapshots aggregateVersion, this version number is incremented each time an event is applied by the aggregate and stored in the snapshot.

This feature was added by Rias who did a great job!

Better protection against concurrency

To make snapshots work, we introduced the concept of a version. The version of an aggregate will increment for each events that was saved. This version will also protected your aggregate against concurrent persists. This can happen when there are two concurrent requests that try to update the same aggregate.

When reconstituting an aggregate from previous events the aggregate will remember the highest version id for that aggregate. If that highest version id differs differs from the highest one that the aggregate remembers, an exception will be thrown.

If concurrent persists should be allowed, you can set the $allowConcurrency static property on the aggregate to true.

use Spatie\EventSourcing\AggregateRoot;

class AggregateRootThatAllowsConcurrency extends AggregateRoot
    protected static bool $allowConcurrency = true;

This feature was suggested by Dries Vints.

In closing

I'm pretty happy with how the snapshot feature turned out, a lot of the users of the package were asking for this and I think we deliver a good, elegant solution.

To know more about the package, head over to the extensive documentation.

Stay up to date with all things Laravel, PHP, and JavaScript.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.



José Cage liked on 14th February 2020
Faisal ahmed liked on 14th February 2020
Usman Irale liked on 14th February 2020
Sebastian Rasch liked on 14th February 2020
🇨🇲 Franck SIYAPZE 🇨🇲 liked on 14th February 2020
Salman Zafar liked on 14th February 2020
Michael Happel Olsen liked on 14th February 2020
Sumon Molla Selim liked on 14th February 2020
togo liked on 14th February 2020
Mike liked on 13th February 2020
Luke Downing replied on 13th February 2020
My favourite thing about url links from @freekmurze is how familiar I’m becoming with his beard and striped T-shirt.
Matthew Poulter liked on 13th February 2020
Spatie retweeted on 13th February 2020
n retweeted on 13th February 2020
Cristian Pallarés liked on 13th February 2020
Cristian Pallarés replied on 13th February 2020
Yesss! Gonna take a look
Hardik Shah liked on 13th February 2020
Lupacescu Eduard liked on 13th February 2020
Anix PasBesoin ⵣ liked on 13th February 2020
Adrian Brown 🕶 liked on 13th February 2020
Arash liked on 13th February 2020
Harish Patel liked on 13th February 2020