Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Stupid Event Sourcing Laravel Package

damgru/stupid-event-sourcing

A Laravel package that adds a simple, no-frills approach to event sourcing. Store and replay domain events to rebuild state, keep an audit trail, and model changes over time without heavy ceremony—aimed at small projects and quick adoption.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Event Sourcing Alignment: The package is a minimalist implementation of Event Sourcing (ES), which fits well in architectures requiring auditability, replayability, or CQRS patterns. Ideal for systems where state reconstruction (e.g., financial transactions, user activity logs) is critical.
  • Laravel Compatibility: Leverages Laravel’s service container, events, and queue systems, reducing friction in adoption. Works seamlessly with Laravel’s Eloquent (if events are tied to models) or standalone.
  • Trade-offs:
    • "Stupid" Design: Prioritizes simplicity over robustness (e.g., no built-in snapshotting, conflict resolution, or complex event versioning). Suitable for greenfield projects or non-critical domains but may require custom logic for production-grade ES.
    • No Distributed Consensus: Lacks features like eventual consistency or multi-node coordination, limiting use in microservices with eventual consistency needs.

Integration Feasibility

  • Core Components:
    • Event Storage: Uses a database table (configurable schema) for events. Works with Laravel’s migrations and query builder.
    • Event Dispatching: Integrates with Laravel’s event system (Event::dispatch()), enabling publish-subscribe patterns.
    • Projection Layer: Requires manual implementation (e.g., via Laravel Jobs or Queues) to rebuild state from events.
  • Dependencies:
    • PHP 8.1+: Ensures modern syntax (e.g., enums, attributes) but may require updates to legacy Laravel apps.
    • Laravel 9+: Assumes newer Laravel features (e.g., spatie/laravel-activitylog compatibility is untested).
    • No ORM Lock-in: Works with raw DB queries or Eloquent, but no active record integration (e.g., no $model->recordEvent()).

Technical Risk

  • Missing Features:
    • No Snapshotting: Replaying all events for large aggregates (e.g., 1M events) is inefficient. Requires custom snapshotting logic.
    • No Event Versioning: Schema changes (e.g., adding fields to events) may break replayability. Needs backward-compatible event design.
    • No Transaction Support: Events are stored after the main transaction commits, risking inconsistency if the app crashes post-dispatch.
  • Performance:
    • Write Path: Fast for single events but may bottleneck under high throughput (e.g., 10K+ events/sec) without batching.
    • Read Path: Rebuilding state from events is CPU-intensive for large event histories.
  • Testing Complexity:
    • Event Replay Testing: Requires test doubles for projections to verify state transitions.
    • Idempotency: No built-in deduplication; custom logic needed for retries (e.g., in queues).

Key Questions

  1. Domain Suitability:
    • Is auditability/replayability a core requirement, or is this overkill for the use case?
    • Are eventual consistency or distributed transactions needed (e.g., for microservices)?
  2. Scaling Needs:
    • What is the expected event throughput? Will batching or async processing be required?
    • Is snapshotting feasible, or will full event replay be too slow?
  3. Operational Overhead:
    • Who will maintain projection logic (e.g., rebuilding aggregates)?
    • How will schema migrations be handled for events (e.g., adding/removing fields)?
  4. Failure Modes:
    • What happens if an event fails to store (e.g., DB error)? Is a dead-letter queue needed?
    • How will out-of-order events be handled (e.g., due to network partitions)?

Integration Approach

Stack Fit

  • Laravel Ecosystem:
    • Events: Replace traditional Model::saved() listeners with Event::dispatch() calls.
    • Queues: Offload event storage to Laravel Queues (e.g., Redis, database) for async processing.
    • Jobs: Use Laravel Jobs to rebuild projections (e.g., RebuildUserAggregateJob).
  • Database:
    • Schema: Extend with a events table (provided by the package) and custom projection tables.
    • Migrations: Use Laravel’s Schema::create() for the event table; manual migrations for projections.
  • Testing:
    • Mock Events: Use Laravel’s Event::fake() for unit tests.
    • Replay Tests: Write integration tests that replay events and assert state.

Migration Path

  1. Pilot Phase:
    • Start with one aggregate (e.g., Order) to test event sourcing.
    • Implement basic event storage and a single projection (e.g., OrderSnapshot).
  2. Incremental Rollout:
    • Add more aggregates (e.g., User, Payment) as needed.
    • Introduce snapshotting for performance-critical aggregates.
  3. Projection Layer:
    • Begin with synchronous projections (e.g., update a current_state table).
    • Gradually move to async projections (e.g., via queues) for scalability.
  4. Observability:
    • Add logging for event dispatching/replaying.
    • Monitor event storage latency and projection rebuild times.

Compatibility

  • Laravel Versions:
    • Tested on Laravel 9+; may need adjustments for older versions (e.g., PHP 8.0).
    • Lumen: Possible with minor tweaks (no built-in event system).
  • Third-Party Packages:
    • Activity Logs: Conflicts with spatie/laravel-activitylog (both track changes). Choose one or sync them.
    • CQRS: Complements packages like spatie/laravel-cqrs but requires manual alignment.
  • Database:
    • Supports MySQL, PostgreSQL, SQLite (via Laravel’s DB layer).
    • NoSQL: Not supported; events must be serializable (e.g., JSON).

Sequencing

  1. Event Design:
    • Define domain events (e.g., OrderCreated, PaymentProcessed) before implementation.
    • Use immutable event DTOs (e.g., classes with __construct only).
  2. Storage Setup:
    • Run the package’s migration to create the events table.
    • Add indexes for aggregate_id and event_id for query performance.
  3. Projection Initialization:
    • Write a bootstrap job to replay historical events into projections.
  4. Dispatch Events:
    • Replace business logic Model::save() with explicit Event::dispatch() calls.
  5. Monitor and Optimize:
    • Profile event replay times and optimize projections.
    • Implement snapshotting for slow aggregates.

Operational Impact

Maintenance

  • Pros:
    • Simple Codebase: Minimal boilerplate; easy to debug.
    • Explicit State Changes: Events act as a single source of truth, reducing "magic" in state transitions.
  • Cons:
    • Projection Drift: If projections aren’t kept in sync, inconsistencies arise (e.g., UI shows stale data).
    • Event Schema Management: Adding/removing event fields requires backward-compatible design and migration logic.
  • Tooling:
    • Event Explorer: Build a Laravel Nova/Forge tool to inspect events.
    • Projection Health Checks: Add cron jobs to validate projections against events.

Support

  • Debugging:
    • Event Replay: Useful for auditing (e.g., "Why was this order canceled?").
    • Challenges: Debugging out-of-order events or missing projections requires tracing through the event log.
  • Documentation:
    • Lack of Official Docs: Relies on GitLab README and source code comments.
    • Community: No active maintainer or community; issues may go unanswered.
  • SLAs:
    • Event Loss: If events aren’t stored before the transaction commits, data loss occurs. Mitigate with transaction observers or database triggers.

Scaling

  • Write Scaling:
    • Throughput: Handles moderate loads (e.g., <10K events/sec) with a single DB.
    • High Load: Requires sharding (e.g., by aggregate_id) or async storage (e.g., Kafka + DB).
  • Read Scaling:
    • Projection Performance: Rebuilding state from events is O(n). Use snapshotting (e.g., store state every 100 events) to reduce replay time.
    • Read Models: Cache **
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator