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 Versionable Laravel Package

overtrue/laravel-versionable

Laravel Versionable is a minimalist package that adds version history to your Eloquent models. Track only changed attributes, keep a set number of versions, whitelist or blacklist fields, and easily revert to any specified version.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • Trait-based augmentation of Eloquent models (use Versionable) backed by a polymorphic versions table. This is the canonical Laravel shape for revision tracking and composes cleanly with the existing model lifecycle (created/updated/deleted events) without forcing a repository or service-layer rewrite.
  • Two storage strategies are exposed — DIFF (default, records only changed attributes) and SNAPSHOT (full versionable attribute set). DIFF keeps payload small for wide tables with a narrow edit surface; SNAPSHOT trades storage for trivial point-in-time reconstruction and simpler audit semantics. The choice is per-model and is the most consequential architectural decision a team will make with this package.
  • Revert mutates the live model through normal save semantics (and by default produces its own new version). withoutVersion() allows suppressing that; correctness here depends on the versioned model's casts/observers, not the package.
  • Diff rendering is delegated to jfcherng/php-diff. That keeps the package minimal but introduces a second dependency (and a second security/support surface) if diff UI is exposed to end users.
  • Version model, table, and foreign key are overridable via $versionModel and trait config, supporting multi-DB and multi-tenant shapes without forking.

Integration feasibility

  • Very high. The entire happy path is: composer require, vendor:publish, artisan migrate, add the trait, declare $versionable (whitelist) or $dontVersionable (blacklist). No queue, cache, external service, or schema change to the parent table.
  • Existing Filament integration (mansoorkhan96/filament-versionable) covers the most common admin-panel UI path.
  • Backfill is the one non-obvious step: the package creates an initial version at model create, not retroactively, so historical rows must be seeded by a one-off job if "history from launch" is an expectation.

Technical risk

  • Retention and growth — every versionable save writes a row. Only manual removeVersion*/forceRemoveVersion* APIs exist; there is no built-in TTL or pruning job. At scale this is the primary long-term risk and a TPM must assign an owner to it.
  • Revert fidelity — revert replays values through normal model save. Casts, encryption, mutators, and observers can make the reverted row not byte-identical to the captured snapshot. Must be validated per versioned model.
  • Eloquent ecosystem interaction — release history shows repeated fixes at the edges (global scopes excluding the model in 5.2.1; lazy-loading prevention in 5.1.3; isForceDeleting guard in 5.2.2). Mature but still interacting with a very large framework surface; your own regression tests are the safety net.
  • Bus factor — single primary maintainer (overtrue) with community PRs. 586 stars and no listed dependents indicates a modest ecosystem footprint. MIT plus small surface area means it is forkable, but security/compat maintenance is best-effort.
  • Major-version drift — v6 drops PHP 8.1/8.2 and targets Laravel 13; 4.x still ships patches. Constraint pinning and a planned upgrade window are required.
  • Data governance — historical rows persist values of versioned columns after parent deletion. This affects GDPR/CCPA erasure and right-to-be-forgotten flows and must be designed in, not retrofitted.

Key questions

  • Which models actually need version history, and is retention driven by legal/compliance need or by UX (undo/revert)?
  • Is DIFF replay acceptable for audit, or does the domain demand SNAPSHOT point-in-time reads?
  • Which versioned columns contain PII, secrets, or regulated data that require redaction or explicit erasure paths?
  • Do we need an in-app diff/browser experience, or is this a back-office capability?
  • What is the write-volume × retention projection, and does it fit the primary database or warrant a dedicated connection/archival tier?
  • What is the fallback if upstream stalls — maintained fork, in-house replacement, or vendor support?
  • Does revert need to be an authorized, confirmed operation with downstream side effects (search index, webhooks, notifications) suppressed?

Integration Approach

Stack fit

  • Laravel 9–13, PHP 8.1+ (5.x line) or PHP 8.3+ (6.x line). Map the constraint to the app's current Laravel/PHP matrix before composer require; do not let Composer resolve a major that silently drops supported PHP versions.
  • No infrastructure change required. Fits monolith, modular monolith, and most Laravel SaaS deployments without queue, cache, or service additions.
  • Coexists with soft deletes, casts, custom primary keys, and custom Version models; known friction is around global scopes, lazy loading, and non-standard relations — covered by shipped fixes but worth integration tests.

Migration path

  1. Pin the major version matching the Laravel/PHP matrix; use 4.x only for legacy stacks.
  2. Publish config and migrations. Review the generated versions table indexes against expected query patterns (by model, by model + created_at for versionAt(), by model + version number, and a created_at index for retention).
  3. Decide storage topology before production writes: primary DB vs a dedicated connection. Moving later requires a data migration.
  4. Enable on one low-risk, high-value model (e.g., CMS page content or product descriptions). Declare $versionable as an explicit whitelist rather than relying on blacklist defaults.
  5. Backfill historical rows with a one-off job if history is expected from day one.
  6. Implement the retention job (scheduled forceRemoveVersions by created_at cutoff) before enabling on any high-write model.
  7. Build or integrate the version browser/diff UI only after the data plane is proven in production.

Compatibility

  • Soft deletes are supported (with the isForceDeleting guard); custom $versionModel and custom foreign keys support multi-tenant; lazy loading is intentionally prevented, so list views must eager-load versions.
  • Diff output supports HTML/JSON/text; apply $stripTags when rendering untrusted user content into HTML.
  • Filament admin surface is supported via a separate plugin; non-Filament UIs require a bespoke version browser.

Sequencing

  • Phase 1 — Pilot one model in non-production; measure row growth, versionAt() latency, and eager-load cost on list views.
  • Phase 2 — Define retention policy, pruning job, and PII redaction/erasure checklist; add monitoring on version-table row count.
  • Phase 3 — Roll out to remaining models in priority order (content > configuration > transactional records), each with its own revert-fidelity test.
  • Phase 4 — Ship UI: version list, diff view, and revert action with authorization and confirmation.
  • Phase 5 — Re-evaluate DIFF vs SNAPSHOT per model based on observed read patterns; migrate selectively if needed.

Operational Impact

Maintenance

  • Low code footprint but a real recurring responsibility: dependency hygiene against a fast-moving Laravel/PHP matrix (v6 already targets Laravel 13 and PHP 8.5 CI) plus monitoring upstream issues for Eloquent-compat regressions.
  • Budget roughly 1–2 engineer-days/quarter in steady state for a low-touch deployment; more if a maintained fork is ever required. The upstream AGENTS.md guidance (minimal diffs, no public API changes, no unnecessary dependencies) is a positive maintenance-discipline signal.
  • Pin to a specific minor. The release history mixes patch-level behavior fixes (5.2.x) with breaking majors (6.0).

Support

  • Community-only: GitHub issues and PRs, no SLA, no vendor. Treat as "supported by us" OSS — a named internal owner is required.
  • The small dependent footprint means fewer external bug reports and fewer battle-tested edge cases; the flip side is a lower chance of third-party integrations beyond Filament.
  • The underlying jfcherng/php-diff dependency is a second support surface; audit it separately if diff rendering is exposed to end users.

Scaling

  • Write amplification is the dominant cost: one INSERT per versionable save. DIFF reduces payload size but pushes cost to reads (reconstructing a version by replaying diffs).
  • Index strategy should mirror access patterns: (versionable_type, versionable_id, version_number), (versionable_type, versionable_id, created_at) for versionAt(), and a standalone created_at index for pruning.
  • At high volume, plan partitioning or archive-to-cold-storage. The package does not ship this; it is an internal build.
  • Reads are cheap with eager loading; the intentional lazy-load prevention means list queries must call with('versions') — a safety default that shifts cost into query design rather than runtime surprises.

Failure modes

  • Unbounded growth — table bloat, backup size, degraded versionAt() scans. Mitigation: retention job, row-count alerting, archive tier.
  • Silent partial versioning — an omission in the $versionable whitelist means revert "succeeds" but does not restore that column. Mitigation: encode the versionable contract in tests and treat the whitelist as a reviewed artifact.
  • Revert side effects — a revert is a write: observers fire, search indexes update, webhooks emit, notifications may send. Mitigation: gate with authorization, confirmation UX, and where necessary withoutVersion plus downstream suppression.
  • Global scope mismatch — version retrieval can silently miss rows depending on scopes applied to the Version model. Mitigation: pin a version containing the relevant fix (post-5.2.1) and cover with integration tests.
  • Erasure gaps — deleting the parent does not cascade historical versions; compliance deletion must explicitly purge them. Mitigation: hook version purge into the standard delete/sanitization flow and document it.
  • Concurrency — concurrent updates can race on version numbering; verify whether gaps/duplicates are acceptable for the domain or require transactional locking.
  • Upstream abandonment — no direct network/IO attack surface, but transitive dependency drift is the practical risk. Mitigation: minimal dependency footprint, pinned versions, and a documented fork contingency.

Ramp-up

  • Very low for a Laravel-fluent engineer: the README is complete, and the API is a handful of methods (versions, latestVersion, versionAt, getVersion()->revert(), withoutVersion, diff). A day of pairing is enough to ship a pilot on a non-critical model.
  • The real learning is in the edges: retention design, DIFF-vs-SNAPSHOT reasoning, revert side-effect management, and PII erasure. Budget 2–3 days of senior review before enabling on any business-critical model.
  • Document the internal contract in the runbook: which models are versioned, which strategy each uses, retention period, who owns pruning, and how erasure is handled. The package itself enforces none of this — the operational posture is entirely a product/engineering decision layered on top of the library.
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.
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
adachsoft/changelog-linter