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

Verbs Laravel Package

hirethunk/verbs

Verbs is an event sourcing package for Laravel artisans that removes boilerplate and jargon, letting you model your domain by what happens—verbs, not nouns. Persist events, rebuild state, and ship faster with a clean, expressive API designed to make event sourcing feel natural in PHP.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • Verbs targets the exact seam where event sourcing is most valuable in a Laravel app: domain aggregates ("states") that emit events, with projections and side effects expressed as Laravel-native listeners. It leans on the service container, facades, Artisan generators, and Laravel's event dispatcher rather than shipping a parallel runtime.
  • The "verbs, not nouns" abstraction (states + events + pending events) is a deliberate DX simplification over textbook event sourcing (aggregate roots, repositories, saga orchestrators). That is a good fit for product teams already fluent in Laravel, but it means adopting Verbs' opinionated model rather than a generic ES library.
  • Notable framework-aware features reduce glue code: Livewire support that commits pending Verbs just before render, queue/outside listeners, a boot phase, and time-travel testing ("wormholes") with historical now() during replay. These are the differentiators versus assembling spatie/laravel-event-sourcing plus custom infrastructure.

Integration feasibility

  • Composer-installable Laravel package with published config/migrations, Artisan state/event generators, and a documented event store schema. PostgreSQL and MySQL are both supported (Postgres added in v0.0.7, MySQL JSON ordering bug fixed in v0.0.8.1), which covers the two most common Laravel production databases.
  • Composer/Laravel version coverage is actively maintained: Laravel 11 compatibility work landed in v0.6.4, Laravel 12 in v0.7.0, and Laravel 13 in v0.8.0. PHP 8.x requirement is implicit from modern Laravel baselines — verify the exact constraint before committing.
  • Integration is additive: it can be introduced into a single bounded context without rewriting existing Eloquent models, since events and states are new classes rather than a mandated persistence replacement.

Technical risk

  • Pre-1.0 API churn is the headline risk. The package is at v0.9.x with a changelog that includes behavior changes in minor releases (dispatcher phase defaults being clobbered by #[Once], nested wormhole warps, state type-hint handling). Any minor bump should be treated as potentially breaking until 1.0.
  • Adoption signal is thin. 522 stars and 0 dependents on the analyzed snapshot means essentially no public downstream ecosystem to lean on for battle-testing, migration notes, or third-party tooling. This is a "small vendor plus community PRs" dependency, not a de facto standard.
  • Replay determinism and serialization are the hard technical edges. The changelog shows ongoing work here (preventing model serialization, cleaning up collection/empty-collection serialization, skipping redundant deserialization, fire no-op during replay, historical now()). Each of those is a class of bug that only surfaces on replay months later — the risk is latent, not immediate.
  • Concurrency guards exist (addressed early in v0.0.3) but the enforcement model and its behavior under queue retries, multi-process workers, and hot aggregates need explicit validation before use on money- or inventory-adjacent domains.
  • No managed event store. Persistence is your relational database; event volume growth, indexing, and snapshot strategy are your operational problem, not the package's.

Key questions

  1. What is the snapshotting story, and at what event count per stream does replay become operationally unacceptable?
  2. How are event schema changes handled — is there an upcasting/versioning mechanism, or is migration of historical events a manual job?
  3. What is the support commitment from hirethunk, and is there a funded maintainer or is this a side project with community PRs?
  4. How do concurrency guards interact with Laravel queue retries and --tries semantics?
  5. Does the event store support multi-tenancy partitioning and per-tenant replay isolation?
  6. What observability exists for replay progress, projection lag, and failed listeners?
  7. Is there a documented path to 1.0, and what is the expected breaking-change cadence?

Integration Approach

Stack fit

  • Best suited to a Laravel 11/12/13 monolith or modular monolith on PostgreSQL (preferred for JSON semantics and indexing) with Redis/queue workers for async projections and outside listeners.
  • Pairs naturally with Livewire, given first-class commit-before-render support, making it viable for interactive apps rather than only API backends.
  • Poor fit for teams that cannot adopt event sourcing wholesale in a context — half-committed ES (events as an audit log bolted onto Eloquent CRUD) is the classic failure mode and Verbs does not defend against it.

Migration path

  • Start with a greenfield bounded context — one aggregate with real behavioral complexity (ordering, subscriptions, approvals) rather than a CRUD entity. Prove the pattern end to end before touching existing domains.
  • Use a strangler pattern for adjacent legacy data: keep Eloquent as the system of record for untouched entities, introduce Verbs states/events for the new context, and bridge via listeners or thin read models. Avoid dual-writing the same entity to both Eloquent and the event store.
  • Expect a one-way door per context: once events are the source of truth, reverting means writing a projection back into tables and accepting loss of history. Scope the first context accordingly.

Compatibility

  • Pin exact versions ("hirethunk/verbs": "0.9.x") rather than using ^0.9. Read every changelog entry before bumping; treat minor releases as breaking until 1.0.
  • Validate against your actual Laravel and PHP version in a spike branch, including the Postgres/MySQL JSON path, before any team-wide rollout.
  • Confirm id_type configuration (snowflake vs UUID vs auto-increment) early — it appears in config and changing it later implies migrating existing event store rows.
  • If using Livewire, verify commit-before-render behavior under your component lifecycle, including nested components and deferred commits.

Sequencing

  1. Spike (1–2 weeks): install in a throwaway branch, model one aggregate, write and replay events, exercise the test helpers and wormhole time-travel testing.
  2. Design (1 week): define the event taxonomy and naming conventions, decide snapshot policy, decide sync vs async projections, define the read-model contract.
  3. Build (3–6 weeks): implement the context behind an existing interface, build projections, wire outside listeners, add the replay drill to CI.
  4. Canary: run the new context in production behind a feature flag alongside the legacy path for one entity, with a scheduled replay verification job.
  5. Expand: only after a clean replay drill and a production incident-free period, onboard the second context. Keep a written rollback procedure.

Operational Impact

Maintenance

  • MIT license removes legal friction but not maintenance risk: with 0 public dependents, you should budget for the possibility of forking and owning the package. Assume a roughly annual internal cost for tracking upstream and rebasing.
  • Watch the changelog and releases on a schedule; the project moves fast enough that skipping several minors creates a compounding upgrade problem.
  • Keep a fork with your own patches for any replay or serialization bugs you hit — turnaround on community PRs is visible (many outside contributors) but not guaranteed by SLA.

Support

  • Documentation (verbs.thunk.dev), README, changelog, and releases are all present and current — better than most 0.x packages. The docs cover states, events, IDs, factories, testing, and customization.
  • Support is community/GitHub-issue based with an active maintainer (inxilpro) and regular external contributions. There is no commercial support tier evident from the package metadata.
  • Plan for internal ownership: designate one engineer as the Verbs subject-matter expert who reviews all state/event changes.

Scaling

  • Event store volume grows monotonically. Define snapshot cadence per aggregate before the first context ships, not after replay latency becomes user-visible.
  • Async projections via queue workers should be the default for anything non-trivial; synchronous projection in the request path will couple write latency to read-model complexity.
  • Concurrency guards serialize writes to hot aggregates — identify high-contention streams (single-tenant counters, shared inventories) and either shard them or accept queued write throughput.
  • Read-model rebuild time is the real scaling constraint. Instrument replay duration per stream and set an alert threshold; if full replay exceeds your maintenance window, you have a snapshot gap.
  • Multi-tenancy: verify whether the event store is partitioned by tenant. If not, per-tenant replay and deletion become manual, expensive operations, and GDPR-style erasure is a genuine problem.

Failure modes

  • Serialization drift: event payloads referencing models, collections, or renamed classes break on replay. The package actively guards against some of this (preventing model serialization, collection fixes), but only for patterns it anticipates. Treat event payloads as a public API and version them.
  • Replay non-determinism: any dependency on wall-clock time, random values, external APIs, or DB reads inside state application will diverge on replay. The historical now() support and fire-noop-during-replay mitigate the common cases but do not eliminate the class.
  • Silent listener failures: outside/queued listeners failing after the event is committed leave read models stale. You need projection-lag monitoring and an idempotent replay-from-checkpoint mechanism.
  • Partial commit / transaction boundaries: verify how pending events commit relative to the surrounding DB transaction, especially under Livewire's commit-before-render path and under queue retries.
  • ID config mismatch: a change in id_type or snowflake settings after events exist is a data migration, not a config change.
  • Version-skew: running mixed package versions across app servers during a deploy can produce incompatible event serialization. Use atomic deploys.

Ramp-up

  • The dominant cost is conceptual, not API: event sourcing, replay, projections, idempotency, and eventual consistency are new mental models for most Laravel developers. Budget 2–4 weeks for a strong mid/senior engineer to be productive on one context, and longer for the team to reason correctly about replay.
  • Verbs' DX genuinely lowers this bar versus generic ES libraries — the "verbs not nouns" framing, generators, factories, and testing helpers are the package's strongest argument.
  • Mitigations: pair the first context with one person who has read the full docs; write an internal short doc capturing your event/state conventions; add a replay drill to CI so the team is forced to confront determinism bugs early rather than in production.
  • Team-level risk: if only one person understands the event store, you have a bus-factor problem on your most critical data path. Rotate review responsibilities deliberately.

Bottom line: Verbs is a well-documented, actively maintained, ergonomic event-sourcing layer that fits Laravel unusually well. The blocker for a TPM is not capability — it is the combination of pre-1.0 API churn, zero downstream dependents, and the fact that replay correctness bugs are latent by nature. Recommend a scoped pilot in one bounded context with pinned versions and a rehearsed replay drill, gated on the key questions above — particularly snapshots, event versioning, and support commitment — before any expansion.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource