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.
Rewind::goTo(), rewind(), fastForward(), restore(), and cloneModel() are one-liners, "restore this record to how it looked yesterday" becomes a shippable feature rather than a research spike. This is a roadmap unlock for admin tooling, CMS-style products, and any surface where customers edit records they later regret.restore() is explicitly non-destructive (creates a new version with event_type = 'restored' and meta['restored_from_version']), while goTo() moves the pointer without an audit record. That distinction is a product decision in itself: you can offer a compliant "revert with recorded justification" path and a separate non-audited "preview" path, and say so accurately in a security questionnaire.versionAt($model, Carbon), getVersionAttributes(), and replay() over a version range enable "what did this record look like on the date of the dispute/audit/invoice?" — a feature that otherwise lands as a bespoke data-warehouse ask.amendCurrentVersion() and excludedFromVersioning() let you keep noisy counters and secrets out of history so the audit trail stays readable by support staff, not just engineers.Rewind::batch() groups multi-model changes under one batch_uuid, so a botched bulk operation becomes an identifiable, queryable unit (RewindVersion::inBatch($uuid)) rather than an archaeology exercise.$rewindStateFields and querying whereStateBecame / whereStateTransition / stateHistory() turns order/payment status history into a first-class, queryable timeline. This supports ops dashboards, SLA measurement ("time from pending to shipped"), and dispute resolution without adding a separate event-tracking system.snapshot_interval (default every 10 versions) is a dial between storage spend and reconstruction latency; pruning (rewind:prune --keep --days) plus per-model $maxRewindVersions gives you a defensible retention policy you can write into a DPA or retention appendix.Consider it when all of the following hold:
current_version column and a versions table via migrations.getVersionAttributes(), replay(), and versionAt() give you the whole row.listener_should_queue for the hot models. Batch versioning and lock-timeout handling (log / event / throw) show the author anticipated concurrency, but you should still load-test your real write path.Look elsewhere — or build — when:
excludedFromVersioning() keeps fields out entirely, but it is not a redaction or crypto layer. Sensitive attributes previously versioned stay in the versions table.updated_at/updated_by columns or an existing activity-log package. Don't buy a reconstruction engine for a "who touched this" widget.One-liner for executives: Rewind is an MIT-licensed Laravel package that adds full version control to our database records — every model change is stored, any version can be inspected, diffed, or restored, and storage stays small because it stores diffs with periodic full snapshots. It converts "audit trail" and "undo" from a multi-sprint build into a configuration task.
Why it matters commercially: it lets us commit to audit and restore capabilities in RFPs and security questionnaires, reduces the support load from accidental edits and bad bulk updates, and gives customers a trustworthy "revert with a recorded reason" workflow — without a bespoke platform investment.
For engineering: a Rewindable trait on the model plus one migration; hybrid diff/snapshot storage with a tunable snapshot_interval; cache-based locking for concurrent writes; queued version creation for hot tables; pruning and per-model version caps for retention; batch grouping across models; and structured state-transition queries for status fields. The API is expressive and the README documents the sharp edges — notably the goTo() vs. restore() audit distinction and how edits on older versions are recorded against the previous head.
Risks to state plainly:
HistoryService interface, keep the ability to swap to a self-built table, and contribute fixes upstream.Recommendation: pilot on a single low-risk, high-visibility model (e.g., CMS content or an internal admin record), measure storage growth and reconstruction latency at our real snapshot_interval, and gate broader rollout — and any compliance claim — on those numbers.
How can I help you explore Laravel packages today?