Skip to content

Legacy Screening Platform Refactor

A screening platform that returned 500s on core screens, spiked two servers, and came with one explanation: "it works on my local". I fixed it by counting first.


Role

Software Engineer, refactor lead

Period

2026, Integrity Asia

Stack

Azure, Azure SQL, Application Insights

Outcome

2 servers → 1, database tier halved


01 — Context

What was actually wrong

Opening two of the platform's core screens ended in an HTTP 500. Everything else was slow, and two production servers of four CPUs and 16 GB each still spiked CPU and memory. When I asked why, the answer was usually the same: "I don't know. It works on my local."

A bug nobody can explain is a bug nobody fixes. So the refactor started with one rule: no fix without a number.

02 — Method

Count first, then cut

Find the cost

Application Insights and the SQL history showed where the time went. It was not the servers. It was the data access layer: one edit flow alone issued 877 SQL statements.

Cut it at the source

Every fix followed the same steps: count the statements, cut them where they are issued, and prove the output is identical before and after.

Make it traceable

Every change has a commit, a source document and a number. A fix that cannot show its before and after is not a fix yet.

Ship when it matters

The release was planned for mid-November. Performance became critical first, so it went to production in October.

Rule
No fix without a number. "It works on my local" is not a measurement.
03 — What broke

Four issues after release. None came from the refactored queries.

They came from what surrounded the application: a sync job that ran outside it under an ambiguous name, browser code without tests, an outdated report template, and a feature users had not been told how to set up. All four were fixed in production or staged within days.

The lesson I keep: a legacy system's real boundary is never its repository. Inventory the jobs, scripts and habits around it before you change what is inside.

04 — Next

Make the invisible SQL visible

Most of the remaining database load came from manually executed SQL, not from the application. I proposed turning those queries into tracked features, so they can be optimised and audited, and direct database access can be restricted.

The same stability made the next step possible: rebuilding the platform properly, instead of under pressure.

05 — Result

2 → 1
Production VMs
~15%
Average CPU, peak ~30%
½
Database tier, both apps

Headroom
Average database usage now sits under 10% of the halved tier, so there is room to halve it again once the manual SQL moves into the application.
Stack
AzureAzure SQLApplication InsightsPerformanceLegacy systems

Next
Case 02
Sales Performance Dashboard →

A sales performance dashboard recomputed everything on demand against a legacy system I was not allowed to touch, query directly, or ask for a push feed. Here is what I could change, and what it cost.