Inherited Laravel marketplace with no documentation and a dead deploy
The original developer had left, nobody could run the project locally, and the only deployment path was copying files onto the server by hand. The owner was afraid to change anything because a failed deploy meant downtime with no rollback.
Engagement
Role: Rescue sprint, founder-led.
Shape: Read-only audit first, then a fixed-scope implementation sprint.
Duration: Audit in 5 business days, sprint in 2–3 weeks.
Stack: Laravel 6 → 10 · PHP 7.4 → 8.2 · MySQL · Redis · Horizon · Pest · GitHub Actions · Docker.
What was wrong
- No local environment: the app only ran on the production server, so every change was tested against live data.
- Deployment was a manual file copy with no rollback path and no record of what had been uploaded.
- Credentials were hardcoded in committed configuration files rather than environment variables.
- Queue jobs and the scheduler were started by hand and silently stopped when the server restarted.
- Several Composer packages were abandoned upstream and pinned to releases with known advisories.
What was built
- Read-only audit first: framework and PHP support status, abandoned Composer packages, and every place credentials were hardcoded.
- Reproducible local and staging environments with a sanitised database seed and written setup steps.
- Characterisation tests around checkout, payouts and authentication before touching application code.
- Git-based deployment with queue workers and the scheduler running as supervised processes instead of cron guesswork.
Architecture after the work
Reproducible environments — Docker-based local setup and a staging environment that mirrors production, seeded from a sanitised database dump with a written README any Laravel developer can follow.
Safety net before change — Characterisation tests in Pest around checkout, payouts and authentication so behaviour was pinned down before refactoring started.
Supervised background work — Queue workers and the scheduler run as supervised processes with Horizon visibility instead of ad-hoc cron entries.
Git-based deploys — Deployment runs from CI on a tagged commit, with the previous release kept for an immediate rollback.
Trade-offs and what was left out
- The jQuery front end was intentionally left in place — replacing it was not needed to make the app safe to change, and a rewrite would have consumed the whole budget.
- Test coverage was written only around the money paths, not the whole application; the remaining gaps were handed over as a prioritised list.
Outcome
The application can be cloned, booted and deployed by any Laravel developer from the README, and the owner has a prioritised list of what was deliberately left out of scope.
Frequently asked questions
- Can an inherited Laravel app be rescued without a rewrite?
- In most cases yes. The first step is a read-only audit that establishes what runs, what is unsupported and what is undocumented. A rewrite is only worth proposing when the existing code cannot be booted or tested at all, which is rare — usually the faster route is reproducible environments, tests around the critical paths and a safe deployment process.
- What happens if the original developer is unreachable?
- Nothing in the process depends on them. The audit works from the repository, the running environment and the database schema, and the handover document records the setup steps that were never written down.