Product Decisions This Supports
- Unblocking unique constraints on soft-deletable entities. The classic conflict — a
users.email unique index versus "let deleted users re-register," or a products.sku unique index versus archived catalog rows — is normally resolved with custom partial indexes, nullable composite keys, or app-level checks. This package reframes it as a storage decision: deleted rows move to a side table, so the primary table keeps clean, narrow unique indexes. That is a real product capability (re-registration, SKU reuse, re-issued handles/slugs), not just an implementation detail.
- Hot-table performance and index selectivity. If deletes are frequent relative to reads, soft-deleted rows inflate the main table, widen every index, and degrade the value of unique indexes. A separate deletion table keeps the operational table closer to "live data only." Treat the claimed performance benefit as a hypothesis to validate against your own delete/read ratios and table sizes — it is not a universal win.
- Data lifecycle and retention strategy. The side table becomes a natural seam for retention policy: how long deleted records are kept, who can see them, when they are purged, and whether they feed audit, support, or compliance workflows. This supports roadmap decisions about a "recycle bin"/admin restore feature, customer-facing undo windows, and GDPR/CCPA deletion pipelines (subject to your own legal review — a side table is still storage).
- Build vs. buy for archival plumbing. The alternative is building a parallel-table archive subsystem yourself: dual-write logic, global scope changes, restore paths, relation handling, migrations. Adopting this package (or forking it) is a cheap way to defer that build. Given the package's maturity signals, the realistic framing is "buy a small head start, budget for ownership," not "buy a supported component."
- Use cases where it fits well: multi-tenant SaaS with account/email re-registration, marketplaces with reusable listing identifiers, catalogs with SKU or slug reuse, admin "trash and restore" features, and any domain where the deleted set is small but the uniqueness constraint is hard.
- Decisions it should not drive: do not let it substitute for a proper audit log (who deleted what, when, why), and do not treat it as a compliance control without legal and security review.
When to Consider This Package
Consider it when most of these are true:
- You are on Laravel and currently fight the soft-delete/unique-index conflict with workarounds (nullable composite indexes,
deleted_at in the unique key, app-level uniqueness checks) that are leaking complexity into product behavior.
- You have a concrete, near-term need: re-registration, identifier reuse, or a restore/trash surface that stakeholders actually want.
- Delete volume or table growth is measurable enough that keeping deleted rows out of the hot table has real value — and you can benchmark it.
- You or your team can read, vendor, and fork a small package. Given one maintainer, a 2021 last release, 36 stars, and zero dependents, you must assume ownership of upgrades.
- The deleted-row model is simple: no complex polymorphic cascades, no heavy reliance on relationship queries against trashed records, no requirement for trashed rows to participate in joins or reporting as-is.
Look elsewhere (or build) when:
- Laravel version compatibility is unverified. A 2021 release predates or barely covers modern Laravel majors. Spike this first; if it does not install and pass your test suite on your target version, the conversation ends there.
- You are on PostgreSQL and a partial unique index (
WHERE deleted_at IS NULL) already solves the business problem. That is a native, zero-dependency answer; do not add a package for it.
- You need audit-grade history. Use a dedicated audit/activity-log package or event sourcing; soft deletes are a lifecycle mechanism, not an audit trail.
- Your deleted data must stay queryable in place — cross-table reporting, foreign keys pointing at soft-deleted rows, or admin tooling that joins trashed and live records. Splitting tables makes those queries harder, not easier.
- You cannot absorb maintenance risk — no capacity to fork, no test coverage around restore semantics, or a platform team that treats unmaintained dependencies as a policy violation.
- Compliance or data-residency requirements demand that you control exactly where deleted data lives; a side table may create a second copy you must also purge, back up, and encrypt — verify this against your obligations.
How to Pitch It (Stakeholders)
For executives: We have recurring product friction where "deleted" records still block customers — a deleted account's email cannot be reused, an archived SKU cannot be reissued. Today we solve this with per-table workarounds that add complexity and slow down schema changes. This package offers a standard pattern: deleted rows move to a separate table so the main table keeps clean unique constraints and stays lean. It is MIT-licensed and small. It is not a supported vendor product — it is a head start we should expect to own and maintain. Recommendation: fund a short, time-boxed spike (compatibility on our Laravel version, benchmark on our two largest tables, restore-path tests) before committing it to the roadmap.
For engineering: It replaces Laravel's built-in soft-delete behavior by relocating trashed rows into a companion table, preserving the original table's schema and unique indexes and reducing bloat in hot tables. The trade-offs are real and must be validated: Laravel major-version compatibility (last release 2021), restore semantics across relations, behavior of global scopes and withTrashed()-style queries, migration strategy for existing soft-deleted data, and backup/retention handling for a second copy of deleted data. We should treat adoption as "vendor and own" — run it through our test suite, benchmark it, and be prepared to fork. If a native alternative (e.g., PostgreSQL partial unique indexes) covers our requirement, prefer that and skip the dependency.
For product: The winning argument is the customer-visible behavior — re-registration, identifier reuse, and a trustworthy restore flow — plus a lower-complexity path than a bespoke archive system. The risk is dependency maturity, so scope the first release to one well-understood domain, measure it, and expand only if the restore semantics hold up under real support scenarios.