plannr/laravel-fast-refresh-database
Speed up database refreshes in your Laravel test suite. This package replaces slow migrate:fresh runs with a faster refresh strategy, so each test starts from a clean database without the long wait. Drop-in, configurable, and built for quick feedback loops.
Architecture fit. The package is a dev-only concern: it targets Laravel's database reset path (migrate:fresh and the RefreshDatabase test trait) rather than application runtime. That is the best possible integration surface — it sits in require-dev, binds through a service provider, and exposes a drop-in trait replacement. Blast radius on production code is effectively zero if the dependency stays out of the production autoload. It aligns with an existing, well-understood contract (RefreshDatabase), so adoption does not require teams to learn a new testing paradigm.
Integration feasibility. High. composer require --dev, swap the trait in the base TestCase (or per-suite), optionally publish config. No application code changes, no schema changes, no infrastructure changes. A competent Laravel engineer can evaluate it in under a day; rollout to a full suite is a one-line diff plus CI verification. The main effort is not integration but validation — proving the fast reset produces the same schema state as the real migration path across every DB engine you test against.
Technical risk.
migrate:fresh path can mask schema drift: tests pass against a reset that production migration history would never produce. Foreign keys, views, triggers, stored procedures, enum/native types, and migrations that cannot run inside a transaction are the usual suspects.Key questions to answer before approval.
artisan test --parallel) — does the reset serialize or collide across workers?schema:dump / squashed migrations, and with multi-connection or multi-database test setups.Stack fit. Well-matched to any Laravel codebase already using RefreshDatabase with PHPUnit or Pest, where migrate:fresh dominates wall-clock time in CI. Best fit where the DB engine is stable and pinned (MySQL 8 or Postgres in Docker) and where parallel testing is already in play — the per-worker reset cost is what this package attacks.
Migration path.
require-dev dependency with an exact-ish constraint (^x.y) and commit the lockfile.App\Testing\FastRefreshDatabase) that extends the vendor trait. This is the single most valuable decision: it gives you a one-line revert and a fork point if upstream stalls.Compatibility. Verify against the exact CI database image, not a locally installed engine. Run the full suite on the fast path — not a subset — before enabling, and specifically target tests touching FKs, polymorphic relations, and raw schema assertions. Treat any test that only passes on the fast path as a drift signal, not a win.
Sequencing. (Sprint 1) Spike + benchmark on a branch; document the measured delta. (Sprint 2) Pilot in one suite, full-suite validation on the fast path, parallel-runner verification. (Sprint 3) Roll out org-wide behind the internal trait, add a note to the testing guide, and record the decision plus the revert procedure in an ADR. Re-evaluate at the next Laravel major upgrade — that is the natural expiry date for this dependency.
Maintenance. Low steady-state cost, but you are the de facto maintainer if upstream goes quiet. Owning the internal wrapper trait means an upstream break is a one-file fix or a hard revert, not a suite-wide outage. Budget a small, recurring line item at each Laravel/PHP upgrade to re-validate — this is the package's only real ongoing tax.
Support. MIT, community-only, no SLA, no vendor relationship. Support burden is internal: designate one owner (typically the engineer who owns CI/test infrastructure) and document the failure signature ("suite suddenly slow" or "FK violations on reset") so on-call triage does not start from zero. The upside of the narrow scope is that the total code surface a team must be able to reason about is small.
Scaling. Gains scale with suite size and worker count, which makes this increasingly valuable as the team and test suite grow — parallel runs multiply the per-reset savings. But returns are bounded: if DB reset is only 20% of suite time, the ceiling is a 20% improvement. Measure first; the ROI case is a CI-minute and developer-feedback-loop number, and it should be justified by that number alone. Diminishing returns arrive once reset time stops being the top bottleneck (usually when the suite shifts to integration/browser tests).
Failure modes to plan for.
migrate:fresh + seed run on the canonical path in a nightly job.Ramp-up. Essentially zero for developers already fluent in RefreshDatabase; the trait swap is invisible to test authors. One hour of onboarding plus a short testing-guide entry covers the team. The real ramp-up cost is concentrated in a single owner who must understand the reset mechanism well enough to diagnose drift — plan for that deliberately rather than assuming it is a "just a dev dependency" decision.
How can I help you explore Laravel packages today?