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

Laravel Rewind Laravel Package

avocet-shores/laravel-rewind

Laravel Rewind gives your Eloquent models full version control: rewind, fast-forward, restore, diff, and query point-in-time state. It stores partial diffs with periodic snapshots for efficient storage and fast reconstruction, plus thread-safe locking, queued versioning, and automatic pruning.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • Rewind is a model-layer concern, not an infrastructure one: one trait (Rewindable), one current_version column per tracked table, and a central rewind_versions table. That means it slots into existing Eloquent domain models without rewriting repositories or introducing a new persistence layer.
  • The hybrid diff/snapshot engine is the core differentiator versus spatie/laravel-activitylog (event log, no state reconstruction) and versus manual *_history tables (full-row copies, storage-heavy). If our requirement is "reconstruct and query point-in-time state" rather than "record that something happened," Rewind is closer to fit than the common alternatives.
  • Batch versioning (Rewind::batch) plus withMeta is the piece that makes this viable for multi-aggregate business transactions (order + line items + shipment), where a per-row audit log is useless for compliance review.
  • The state-transition layer ($rewindStateFields, whereStateTransition, stateHistory) is a genuine architectural accelerator if our roadmap includes status-lifecycle analytics — it is otherwise a bespoke table we would build ourselves.

Integration feasibility

  • Onboarding is shallow: composer require, publish provider (migrations + config), rewind:add-version to generate the per-model migration, add trait. A single engineer can pilot on one model in under a day.
  • Existing rows are not retroactively versioned; the package gives initVersion() for baselines. Any "we need history from day one of the contract" requirement must be handled by a backfill job we own.
  • Locking is cache-based. This is the single most important integration constraint: it presumes a shared, atomic lock store (Redis/Memcached/DynamoDB). Apps still on file or array cache in multi-node deployments will silently lose the concurrency guarantee.
  • Config surface is small and legible (snapshot_interval, listener_should_queue, on_lock_timeout, max_versions, prune_*, version_model) — everything a TPM would want tunable per-environment is tunable.

Technical risk

  • Maturity risk, high. 209 stars, 0 dependents, pre-1.0 changelog line (v0.9.0). There is no downstream body of production usage to lean on; we would be an early design partner, not an adopter of a proven component. Package score (~19.6) and low opportunity signal reinforce limited ecosystem pull.
  • Bus-factor risk. Single named maintainer (Jared Cannon). Bus factor 1 on a component that would sit on the critical path of an audit/compliance capability.
  • Correctness risk in the interesting cases. Hybrid storage plus pruning plus "edit while rewound" is a non-trivial state machine. The README is explicit that editing from a rewound position rebases old_values on the previous head, which is defensible but surprising; auditors and support engineers will need that explained once, correctly, in our runbook.
  • Semantic misuse risk. goTo() (moves pointer, no record) versus restore() (creates an audited version) is exactly the kind of distinction product teams get wrong. A compliance officer reviewing history will not accept a "pointer move."
  • Eventual consistency risk. listener_should_queue: true buys write throughput but means version rows lag the model update and can arrive out of order relative to the lock window. Acceptable for high-write telemetry-ish tables, unacceptable for the tables feeding the audit trail.

Key questions

  1. What Laravel/PHP versions are supported in composer.json, and is there an LTS-aligned support policy?
  2. Which cache driver and topology did the maintainer test locking against at concurrency > 1? Is there a documented failure test?
  3. What is the versioning/BC policy pre- and post-1.0? Is there a stated 1.0 date?
  4. How is the rewind_versions table expected to be indexed and partitioned at 10M+ rows?
  5. Does queued creation preserve per-model ordering, or can v_n land after v_n+1?
  6. Is there a documented answer for "prune interacts with an in-flight restore"?

Integration Approach

Stack fit

  • Native Laravel/PHP; no sidecar, no external service, no SDK. It inherits our existing DB, cache, and queue — which is good for ops simplicity and bad for blast radius (a slow versioning write becomes a slow user-facing write unless queued).
  • Fits our existing conventions (trait + published config + artisan commands) almost exactly, so no framework-level objection.
  • Does not fit if the org standardizes on event sourcing or CDC (Debezium/Kafka) for audit — Rewind would be a duplicate, divergent source of truth. Resolve that politically before the pilot.

Migration path

  • Greenfield models: trivial — trait plus the generated current_version column, versions accrue from first insert.
  • Brownfield models: two-step. Ship the schema migration (nullable current_version, default handling for existing rows), then a one-off initVersion() backfill so navigation has an anchor. The backfill must run before users are told "history exists."
  • No data migration away from an existing audit table is provided; if we are replacing an in-house history table, we own the reconciliation and the dual-write window.

Compatibility

  • Requires a shared cache lock backend; requires queue workers if queued mode is enabled; requires MySQL/Postgres JSON column support for old_values/new_values/meta.
  • Interacts with anything that mutates models outside Eloquent (raw DB::update, bulk upsert, queue workers using withoutEvents) — those paths will not version, silently. Enumerate them.
  • Custom version model hook (version_model) is our escape hatch if we need tenancy columns or additional indexes; verify it doesn't conflict with future package upgrades.

Sequencing

  1. Spike (1 sprint): pilot on one low-risk, high-edit-volume model. Validate lock behavior under load with the target cache driver.
  2. Harden: decide queued vs. synchronous per model class; define exclusion lists (excludedFromVersioning) for secrets and derived fields; confirm snapshot_interval against measured reconstruction latency.
  3. Expand: two to three models covering a real business flow, wired to Rewind::batch so we prove cross-aggregate history before promising it.
  4. Product surface: expose diff / stateHistory in the admin UI behind a feature flag — this is where the package earns its keep or doesn't.
  5. Operationalize: schedule rewind:prune, set max_versions defaults, alert on RewindVersionLockTimeout.

Operational Impact

Maintenance

  • Ongoing cost is mostly schema and storage hygiene, not code: unmanaged version tables grow without bound. Pruning must be scheduled on day one, not after the first incident. The --keep / --days combination with --pretend gives us a safe tuning loop.
  • Upgrades are the real risk: pre-1.0, single maintainer. Budget for the possibility of forking. MIT license makes that legally clean; the cost is engineering time and losing upstream fixes.
  • Our own maintenance obligation: documenting the goTo vs restore distinction and the rebase-on-edit behavior in internal runbooks. That is product-team work, not library work, and it is unavoidable.

Support

  • No vendor, no SLA, no paid tier. Support = our platform team reading source and issue tracker. Issue-response latency is an unknown; treat first-line support as internal.
  • Community is thin (209 stars, 0 dependents) — Stack Overflow coverage will be near zero. Everything the team learns about this package must be written down internally within the pilot.
  • Upside: MIT, small codebase, readable, tests + Codecov + code-style CI in place. Debuggability is genuinely better than a closed or heavyweight alternative.

Scaling

  • Write path: one model write becomes one model write + one version insert (+ optional queue dispatch), serialized per model by a cache lock. Throughput ceiling is the lock, not the DB. High-write models must be queued or excluded.
  • Read path: getVersionAttributes / replay reconstruct from the nearest snapshot. snapshot_interval is the direct knob between storage cost and reconstruction latency; the default of 10 is reasonable but should be measured against our largest expected diff (wide rows with JSON columns).
  • Storage: roughly (1/snapshot_interval) full rows plus per-change diffs. Predictable, but the rewind_versions table will become one of the largest in the schema. Index plan and retention policy are prerequisites, not follow-ups.
  • replay reconstructs incrementally across a range, so analytics over wide ranges stay linear rather than quadratic — this is the strongest scaling claim in the README and worth verifying in the pilot.

Failure modes

  • Lock timeout. Configurable: log (silent — dangerous default for us), event (dispatch and handle), throw (retry-friendly with queued listeners). Recommend event or throw in production; log risks invisible history gaps that only surface during an audit.
  • Queued versioning lag/ordering. Versions arrive late; a user diffing immediately after a save sees stale data. Mitigate by keeping audit-critical models synchronous.
  • Prune against a live pointer. Pruning converts the new oldest version into a snapshot; if a user is parked on a pruned version, behavior needs a product answer (404 vs. snap to oldest). Test this explicitly.
  • Silent non-versioning. Raw queries, withoutEvents, and excluded attributes create gaps. Any compliance claim resting on this package must state those gaps.
  • Model deletion. deleted is a tracked event type, but soft-delete vs. hard-delete semantics for history retrieval after delete need to be confirmed before we promise "nothing is ever lost."
  • Storage exhaustion. Unbounded growth on a busy table is the most likely operational incident. Alert on table size, not just on prune job success.

Ramp-up

  • Engineer ramp-up: low, a few hours — trait plus facade plus artisan commands.
  • Organizational ramp-up: moderate. The concepts that need teaching are goTo vs restore, snapshot interval, and what is excluded from tracking. Budget an internal brown-bag and a one-page decision record.
  • Adopt in a team that already understands Eloquent lifecycle events; do not adopt as a first audit feature on a team unfamiliar with versioning semantics — the package is honest about its edge cases but does not scaffold the product decisions around them.
  • Verdict for a TPM: viable for a scoped, internal pilot on non-critical models; not yet appropriate as the sole audit-of-record for regulated data without a fork-and-own plan or a contractual fallback.
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.
mydnic/volet-feature-board-filament-plugin
wmde/email-address
refinery29/test-util
dees040/laravel-api-responses
teamzac/geocoder
ideatica/config-writer
keaton-php/pipe-dream
jacksonwebservices/laravel-user-suite
maksimru/conditional-laravel-debugbar
gismatul/nova-support-chat
gismatul/laravel-support-chat
networkrailbusinesssystems/oracle-api
alphabalex/messaging-made-easy
rawphp/warp
shootkiran/merobug
narakode/fineauth
numencode/wn-syncops-plugin
ibnnajjaar/mib-global-pay
refinery29/php-cs-fixer-config
parsnick/steak