02
AD CAMPAIGN DATA INTEGRITY
Reconciled an ad platform's client, campaign and delivery-unit data across three master sources and the APIs on top of them, and proved where the documented behaviour and the live system disagreed.
- Role
- Careers360
- Stack
- SQL · MySQL · Python
- Year
- 2026
- Status
- In production
Context
An advertising platform where one client record fans out into campaigns, and each campaign into the delivery units that actually run. Three client categories sit behind that single screen, and each one draws its entities from a different master table under a different rule about what may be attached and where it may come from.
That shape makes drift cheap and silent. A record can read one way in the admin UI, a second way from the API and a third way in the table underneath, and nothing anywhere throws. The first person to notice is a client looking at a report that does not match what they bought.
The written spec was spread across sibling tickets that contradicted each other, and ticket status tracked intent rather than reality: work marked done was sometimes not deployed, and work marked open was already serving traffic. Taking either the spec or the board at face value would have produced a confident, wrong answer.
Approach
- 01
Rebuilt the data model from the live schema instead of the document: which master table feeds each client category, which keys carry the association, and how a soft delete marks a row as gone while leaving it joinable.
- 02
Read every record three ways, querying the database directly in Python and comparing it against the same record from the API and the admin UI, rather than trusting any single surface.
- 03
Reconstructed the campaign state machine from live data and found the documented status mapping was inverted for two of the four states, which meant every draft count derived from it was describing the wrong set of rows.
- 04
Traced an asset field that never populated back to its source and showed the application was reading a table that had never held that data, while the real values sat in a different master table all along.
- 05
Separated genuine spec violations from legacy rows that predate the current rules, so the fix list reflected the policy rather than the history, and flagged the ambiguous ones instead of quietly picking a side.
- 06
Established what could not be verified at all: one feature's backing table was empty in the test environment, so the conflict and locking behaviour had no path to proof. Reported it as untestable rather than passing it.
- 07
Kept direct database writes out of permission and editability testing, because writing straight to the table bypasses the exact validation layer under test and turns a real check into a green tick that proves nothing.
- 08
Wrote every finding with the query and the request that reproduce it, so each one could be confirmed by someone else without rerunning my session.
Results
- records breaking the stated rules
- 1135
- database and API in agreement
- 100%
- status codes the docs got wrong
- 2
- findings without proof attached
- 0
Stack
- SQL
- MySQL
- Python
- REST APIs
- Schema Analysis
- Data Quality
Architecture sketch: AD CAMPAIGN DATA INTEGRITY
OPTI-RECOURSE
COLLEGE PREDICTOR DATA VALIDATION