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 Auto Hard Deleter Laravel Package

sbamtr/laravel-auto-hard-deleter

Automatically hard delete soft-deleted Eloquent models after a configurable retention period. Add a trait to your models, set how long records should linger in the trash, and let Laravel's scheduler permanently purge them, with no manual cleanup jobs required.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package addresses a real and narrow gap in Laravel's Eloquent lifecycle: SoftDeletes gives you a reversible delete, but ships no mechanism for eventual purge, so deleted_at rows accumulate indefinitely. The implementation pattern — a trait applied to a model declaring a retention window, paired with a console command that iterates expired rows and calls forceDelete() — sits cleanly inside idiomatic Laravel and requires no infrastructure. Architecturally, however, it places a data-governance policy (retention) inside the domain model. For a TPM, that framing matters: retention is typically owned by legal/compliance and expressed as configuration, not as a property hard-coded on a class. A package that cannot externalize retention to config or policy layer will be awkward to audit.

Integration feasibility. Mechanically trivial: composer require, add the trait, set the window property, register the command in the scheduler. First-pass integration is an afternoon, not a sprint. The blocker is not effort — it is version viability.

Technical risk. This is the dominant finding and it is high:

  • Archived, last release 2022-02-10. The repository is read-only and predates Laravel 10, 11, and 12. Expect the composer constraint to cap out at Laravel 8 (possibly 9) and to conflict with modern illuminate/support. If it does install via a loose constraint, that is worse — untested code paths against a framework whose soft-delete internals have moved.
  • Zero dependents, 47 stars. No ecosystem validation. There is no evidence of production use at any scale, which means no bug reports, no edge-case hardening, and no signal on how the command behaves against large tables or unusual schema.
  • Destructive operation at the highest blast radius. Auto-purge is the one feature in a Laravel app that cannot be un-done and cannot be recovered from a rollback. Shipping it via an unmaintained third-party dependency inverts the usual risk calculus.
  • Suppressed maintenance and no CVE path. Archived status means no security response, and dependency scanners will (correctly) raise abandonment flags in your supply chain review.

Key questions to resolve before any decision:

  1. What is the declared Laravel/PHP support matrix in composer.json, and does it resolve against our current framework version?
  2. Does the command chunk() expired records, or load the full result set into memory?
  3. Does it call forceDelete() per model instance (firing model events and observers, N queries) or issue a mass query delete (fast, but silently bypasses observers, file/media cleanup, and downstream cascade logic)?
  4. Is the retention window per-model only, or can it be driven from config/environment?
  5. Is there any dry-run, report-only, or logging mode?
  6. How does it behave with non-standard deleted_at column names, multi-tenant scopes, or global scopes on the model?
  7. Does the scheduler entry use withoutOverlapping()?

Integration Approach

Stack fit. If the platform is on Laravel 8 or earlier, adoption is technically viable. On Laravel 9+, assume it does not fit without a fork and patch. Given Archived: yes and a release date over three years stale, the realistic recommendation for any actively maintained stack is: do not adopt the package; adopt the pattern.

Migration path. The functionality is roughly 100–150 lines of first-party code and is low-risk to own:

  • A PurgeSoftDeletedRecords artisan command accepting --model, --days, --dry-run, --chunk, --limit.
  • A config/retention.php mapping each soft-deletable model to a retention window, sourced from env where compliance requires it.
  • A scheduler entry with withoutOverlapping() and a bounded runtime.
  • Chunked deletes with an explicit index on (deleted_at) per table.

This replaces the dependency entirely, removes the supply-chain finding, and puts retention under configuration review — which is where auditors expect to find it.

Compatibility. If a fork is preferred over a rewrite (e.g., to preserve existing behavior), vendor the package under an internal namespace, tighten the composer constraint to the versions actually tested, and wrap the trait in an application-owned trait so the underlying implementation can be swapped without touching 20 models. Either way, verify against the current framework: the SoftDeletes trait's forceDelete() contract and deleted_at handling have been stable, but the package's assumptions about them were never tested past 2022.

Sequencing.

  1. Inventory every model using SoftDeletes; there are usually more than anyone expects.
  2. Classify each by retention obligation (regulatory, contractual, or "no one has thought about it").
  3. Set windows with legal/compliance sign-off, not engineering guesswork.
  4. Build the first-party command with dry-run as the default posture.
  5. Run report-only for at least two weeks; compare predicted purge counts against expectations.
  6. Enable per model, starting with the lowest-value, highest-volume table.
  7. Add audit logging (count purged, model, window, run id) before enabling the destructive path anywhere.
  8. Only then enable cascade-sensitive models — and audit foreign keys first.

Operational Impact

Maintenance. Archived means you own it from day one. Budget either a fork maintenance line item or the rewrite. The rewrite is almost certainly cheaper than carrying a vendored orphan for multiple framework upgrades.

Support. No upstream maintainer, no issue triage, no security advisories. With zero dependents there is no community to fall back on. Automated dependency and supply-chain scanners will flag this permanently; the exception request will outlive the engineer who filed it.

Scaling. This is the area where thin packages of this age most often fail. Naive implementations iterate the full expired set in PHP, which is a memory incident waiting for the first large table. Hard-deleting millions of rows in a single transaction causes table locks, write-ahead log / binlog bloat, replication lag on read replicas, and lock contention with live traffic. Mitigations must be explicit: chunked deletes (1k–5k per batch), a sleep() between batches, an index on deleted_at, off-peak scheduling, and a hard row-limit cap per run. Verify these are present before enabling — do not assume.

Failure modes to design against:

  • Cascading FK deletes. onDelete('cascade') means purging a parent silently removes children that may have their own retention obligations. Audit FKs before the first production run.
  • Bypassed observers. Mass-delete paths skip model events, orphaning media, search indexes, and downstream syncs. If the package uses per-model forceDelete(), the inverse risk applies: an observer throwing mid-batch leaves partial state.
  • Retention misconfiguration. A 0 or null window interpreted as "delete now" is a one-line data-loss event. Validate configuration at boot and refuse to run on ambiguous values.
  • Scheduler overlap. Long-running purges re-triggered without withoutOverlapping() compound lock pressure.
  • Clock/timezone skew against deleted_at, causing premature purges.
  • No dry-run. Without a report-only mode, the first bug discovered is a production data-loss incident rather than a log line.

Ramp-up. Developer ramp-up is negligible — the trait-plus-command pattern is immediately legible to any Laravel engineer. The real ramp is organizational: establishing who owns the retention policy, who signs off on windows, and who is paged when a purge run behaves unexpectedly. That work is identical whether you adopt the package or build it, which further weakens the case for the dependency.

Verdict. Low score (0.1625), archived, zero dependents, and a destructive core function is a disqualifying combination. Reimplement the pattern in-house behind a config-driven, dry-run-first command. The package is a useful reference design, not a dependency.

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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log