At some point every owner of an ageing PHP application hears the word "audit". Sometimes from a developer who wants to help. Sometimes from an agency that wants the rebuild that usually follows. The word covers everything from a five-minute Lighthouse screenshot to a six-week consulting engagement, so it is worth being precise about what a serious one actually contains.
This article walks through the anatomy of a real audit we performed on a revenue-generating legacy PHP platform — an equipment-hire business whose bookings, payments, invoicing and content all ran through one ageing codebase. Details have been altered to protect the client; the structure and the kinds of findings are exactly what to expect.
What an audit is not
Three things get sold under the name that are not the real thing:
- A Lighthouse screenshot. Page-speed scores are one data point in one of five areas. They say nothing about whether your backups work.
- A linter dump. Automated tooling output ("4,120 code style violations") describes the code, not the risk to your business.
- A rewrite pitch. If the conclusion was written before the audit started, it is a sales document. Most legacy systems that earn money need stabilising, not replacing.
A real audit answers one question: what could hurt this business, in what order, and what should be done about it?
The five areas a real audit examines
Ours aggregated five separate investigations into one report. Each looks at the system from a different direction, and the worst findings usually sit in the gaps between them.
1. Infrastructure
Where does this actually run, and what happens when it fails? In this audit: the application and its database shared a single cloud server, with no automated backups anyone could point to, no restore ever rehearsed, months of pending security patches, and an instance sized for several times the observed load — money spent on capacity while the actual risk was continuity.
2. The database
The schema tells you the system's real history. Here: roughly seventy tables, of which only a handful had foreign-key constraints; a dozen still on a storage engine deprecated years ago; prices, statuses and dates stored as free-form text; structured business data serialized into blobs no report could query. And the repository contained just two migrations — the real schema lived only in production, unversioned, which makes every deployment a small act of faith.
3. The codebase
Not style — safety. The findings that mattered: routes reachable from the public internet that could mutate production data, including leftover migration and maintenance helpers; admin permission checks that had been effectively disabled at some point and never restored; credentials committed to the repository; controllers of enormous size with billing logic woven through them; no transactions around multi-step payment and invoicing flows; and effectively zero automated tests around anything that earned money.
4. The application's history
Legacy systems carry their migrations with them. This platform had been moved off an older CMS years earlier — but incompletely, so the old system's structures, domains and even a second runnable legacy application still lived inside the current one's public directory, quietly expanding the attack surface and confusing every change.
5. Deployment and operations
Who can deploy, how, and what happens when it goes wrong? Here nobody could fully describe the deployment path, access was broader than anyone intended, and monitoring was thin enough that the business would learn about most failures from customers.
The part that makes it an audit: priority by business impact
A findings list is not the deliverable. The deliverable is the order. Every finding in the report is priced in business terms — outage risk, data loss, revenue leakage, regression risk, wasted spend — and then sequenced. For this platform the order was:
- Protect the business — close the public production-changing routes, restore access control, rotate exposed credentials, get backups working and tested, patch the server. Days, not months.
- Make change safe — version the schema, add transactions around money flows, put tests around the paths that earn revenue.
- Then grow — performance, technical SEO, conversion-critical journeys. Only now do the Lighthouse scores get their turn.
- Then save money — rightsize the oversized server, commit to reserved pricing, once the platform is stable enough to measure.
Note what is last. The infrastructure savings were real — but cutting costs on a platform that could lose its data is optimising the wrong thing first. An audit that leads with the savings is telling you what you want to hear.
The overall verdict followed the same logic: this business did not need a rebuild — it needed a stabilization program before any feature roadmap. That sentence, backed by evidence, changed how the owner planned the next two quarters.
What you should walk away with
A serious audit of a legacy PHP application hands you four things in writing:
- A findings report across all five areas, each finding stated with its business impact, not just its technical description.
- A prioritised, phased plan with rough timelines — what happens in the first week, the first month, the first quarter, and why in that order.
- A decisions list — the questions only you can answer, made explicit instead of assumed.
- Independence. The report is yours. It must be usable with any team, including the one that wrote none of the code — otherwise it is a proposal, not an audit.
Where we fit
This is the work our System Risk Check productises: a fixed-price audit of your application, database, infrastructure and deployment path, delivered as a written, prioritised report. Owners use it before taking over an inherited system, before committing to a big roadmap on an ageing one, or simply to find out whether the anxiety about their platform is justified. Sometimes it is not — that is a good report too. When it is, you will know exactly what to do first, and what can safely wait.

