DEV Community

Cover image for Laravel Event Sourcing: From Aggregates to Projectors

Laravel Event Sourcing: From Aggregates to Projectors

“Your app’s history is as important as its current state.”- Every Enterprise Developer Ever

Event sourcing is a powerful architectural pattern that treats every change in your application as an event. If you’re building complex systems where audit trails, historical data, and state changes are critical, Laravel event sourcing is a game-changer.

This guide walks you through mastering Laravel event sourcing, from setting up aggregates and projectors to building scalable, auditable applications.

Key Takeaways

  • Use aggregates for business logic and state management
  • Use projectors for read models and reporting
  • Use reactors for side effects
  • Version events and plan for migration
  • Ensure events are immutable and idempotent
  • Event sourcing makes your Laravel apps auditable, scalable, and maintainable.

Index

  1. Why Laravel Event Sourcing Matters
  2. How Laravel Event Sourcing Works
  3. Aggregates vs Projectors
  4. Setting Up Event Sourcing in Laravel
  5. Creating Aggregates
  6. Building Projectors
  7. Handling Events and Event Queries
  8. Using Reactors
  9. Event Versioning and Migration
  10. Common Mistakes to Avoid
  11. FAQs
  12. Interesting Facts & Stats
  13. Conclusion

1. Why Laravel Event Sourcing Matters

Event sourcing ensures every action in your application is recorded as an immutable event. This makes it possible to:

  • Reconstruct any state at any point in time
  • Audit and debug changes easily
  • Build powerful reporting and analytics
  • Scale read and write operations independently Without event sourcing, complex applications often lose historical context and become hard to maintain. Laravel, with packages like Spatie’s laravel-event-sourcing, makes it easy to adopt this pattern.

2. How Laravel Event Sourcing Works (The Basics)

Event sourcing in Laravel revolves around:

  • Events: Represent changes (e.g., UserCreated, OrderPlaced)
  • Aggregates: Entities that record and replay events
  • Projectors: Classes that update read models based on events
  • Reactors: Classes that trigger side effects (e.g., sending emails) Example:
$user->create(['name' => 'John'])->recordThat(new UserCreated(['name' => 'John']));
Enter fullscreen mode Exit fullscreen mode

Each event is stored, and the aggregate’s state is rebuilt by replaying events.

3. Aggregates vs Projectors

Aggregates:

  • Hold business logic and state
  • Record and replay events to rebuild state
  • Ensure consistency Projectors:
  • Listen to events and update read models (e.g., database tables)
  • Enable fast queries and reporting
  • Decouple read and write logic

4. Setting Up Event Sourcing in Laravel

Install the Spatie package:

composer require spatie/laravel-event-sourcing

Enter fullscreen mode Exit fullscreen mode

Publish the configuration:

php artisan vendor:publish --provider="Spatie\EventSourcing\EventSourcingServiceProvider"

Enter fullscreen mode Exit fullscreen mode

Create your event store migration:

php artisan make:migration create_stored_events_table

Enter fullscreen mode Exit fullscreen mode

Configure your event store model and repository as needed.

5. Creating Aggregates

Generate an aggregate:

php artisan make:aggregate UserAggregate

Enter fullscreen mode Exit fullscreen mode

Example:

class UserAggregate extends AggregateRoot
{
    public function createUser(array $attributes)
    {
        $this->recordThat(new UserCreated($attributes));
        return $this;
    }
}

Enter fullscreen mode Exit fullscreen mode

Aggregates handle business logic and record events.

6. Building Projectors

Generate a projector:

php artisan make:projector UserProjector

Enter fullscreen mode Exit fullscreen mode

Example:

class UserProjector extends Projector
{
    public function onUserCreated(UserCreated $event)
    {
        User::create($event->attributes);
    }
}
Enter fullscreen mode Exit fullscreen mode

Projectors update read models for fast queries.

7. Handling Events and Event Queries

Events are stored in the event store. To query events:

$events = StoredEvent::where('aggregate_uuid', $uuid)->get();

Enter fullscreen mode Exit fullscreen mode

Replay events to rebuild state:

$aggregate = UserAggregate::retrieve($uuid);

Enter fullscreen mode Exit fullscreen mode

This allows you to reconstruct any state from events.

8. Using Reactors

Reactors trigger side effects (e.g., sending notifications):

class UserReactor extends Reactor
{
    public function onUserCreated(UserCreated $event)
    {
        Mail::to($event->attributes['email'])->send(new WelcomeEmail());}}

Enter fullscreen mode Exit fullscreen mode

Reactors keep business logic and side effects separate.

9. Event Versioning and Migration

When events change, version them:

class UserCreatedV2 extends UserCreated
{
    // new structure
}
Enter fullscreen mode Exit fullscreen mode

Migrate old events to new versions to maintain compatibility.

10. Common Mistakes to Avoid

  • Not versioning events
  • Storing mutable state in events
  • Overloading aggregates with too much logic
  • Ignoring idempotency in event handling
  • Not planning for event store growth

11. FAQs

Q. When should I use event sourcing?
When you need audit trails, historical data, or complex state changes.

Q. Can I mix event sourcing with traditional models?
Yes, use event sourcing for critical parts and traditional models elsewhere.

Q. How do I handle event store growth?
Use database partitioning, archiving, and optimization.

Q. What if an event is missing?
Replay events to rebuild state or fix the event stream.

Q. Can I use event sourcing for small apps?
Only if you need the benefits; otherwise, it adds complexity.

12. Interesting Facts

- Laravel’s event sourcing concepts
This covers why event sourcing works well for audit trails and fits Laravel/CQRS architectures.https://laravel-news.com/event-sourcing-in-laravel Laravel News
- MoldStud article noting debugging and audit trail benefits
Discusses how using event sourcing helps trace state changes and can cut debugging time by replaying events. https://moldstud.com/articles/p-managing-data-consistency-in-laravel-microservices-best-practices-and-strategies MoldStud
- Spatie Laravel Event Sourcing documentation
Explains how event sourcing in Laravel supports auditability and reporting needs.https://spatie.be/docs/laravel-event-sourcing/v7/introduction Spatie
- Event sourcing & CQRS patterns overview (general context)
Shows broader adoption of these patterns and why they’re used in event-driven architectures.https://medium.com/techartifact-technology-learning/event-driven-architecture-with-cqrs-event-sourcing-bdded2f3c595

13. Conclusion

Event sourcing is a powerful pattern for building robust, auditable, and scalable Laravel applications. By using aggregates, projectors, and reactors, you can decouple business logic, reporting, and side effects. Whether you’re building a CRM, banking app, or e-commerce platform, event sourcing ensures your system is maintainable and future-proof.

About the Author: Lakashya is a web developer at AddWebSolution, building scalable apps with PHP & React. Sharing ideas, code, and creativity.

Top comments (0)