Laravel Event Sourcing: Basics
Laravel Event Sourcing: Basics
Laravel Event Sourcing: Basics
Tip: Store Events, Not State
event(new OrderCreated($orderId, $items));
event(new OrderPaid($orderId, $amount));
Each event represents a state change.
Gotcha: Events Are Immutable
Once stored, events should never be modified. Append new events to correct mistakes.
Tip: Projectors Rebuild State
class OrderProjector
{
public function onOrderCreated(OrderCreated $event): void
{
Order::create(['id' => $event->orderId, 'status' => 'created']);
}
}
Gotcha: Event Ordering Matters
Events must be processed in the order they occurred. Use timestamps or sequence numbers.
Tip: Snapshots for Performance
$snapshot = OrderSnapshot::where('order_id', $id)->latest()->first();
$events = Event::where('order_id', $id)->after($snapshot->sequence)->get();
Skip replaying all events by starting from a snapshot.
Gotcha: Event Versioning
Include a version field in events to handle schema evolution over time.
Tip: Use route:cache Carefully
php artisan route:cache is fast, but it doesn't work with closure-based routes. Every time you cache routes, Laravel serializes them. If you have Route::redirect() or closure callbacks, the cache breaks. Stick to controller-based routes in production.
Tip: Model APP_KEY Rotation
Rotating APP_KEY invalidates all encrypted data — cookies, encrypted DB columns, and password reset tokens. If you must rotate (e.g., after a leak), plan a migration that re-encrypts existing data with the new key.
Gotcha: Local Scope Leaks
Global scopes defined in booted() apply to ALL queries on that model — including relationships. An innocent User::all() in admin panel might exclude soft-deleted users if a global scope is active.
Senior Insight
Event sourcing is a powerful pattern, but it's overkill for most applications. I've consulted on projects where the team implemented event sourcing because it sounded cool, only to realize they needed simple audit logging. If you don't need to rebuild state from events or query historical states, you probably don't need event sourcing. Start with Laravel's native audit features and only adopt event sourcing when the requirements explicitly demand it.
Source: Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/laravel), Spatie Blog (https://spatie.be/blog)