Platform rebuild

When patching isn't an option: rebuilding the foundation

A paid feature commitment to ScopeWorker's largest client couldn't be bolted onto a 7-year-old page. So I rebuilt the foundation — and mapped every write path in the platform to keep 70 columns of data in sync.

My role
PM — diagnosis, scope, spec, sprint mgmt, QA
Team
3 senior engineers + me
Timeline
~2.5 months
Load time
15–20s → 3–4.5s
~75–80%
page load time reduction
70+
columns kept in real-time sync
Paid commitment
delivered to largest client
93%
avg user satisfaction, post-launch
The rebuilt contract dashboard — main view
Afterfig.01The rebuilt contract dashboard — the entry point every buyer lands on first.
The business problem

A feature was already sold. The page under it couldn't support it.

T-Mobile, ScopeWorker's largest client, had purchased advanced condition-based search and saved views as a paid add-on. Delivering it wasn't optional — it was a commitment already sold.

The problem: neither feature could be built on top of the existing contract dashboard. The page was a ~7-year-old legacy build that couldn't support the new functionality. And for T-Mobile specifically — with 2.3 million contracts created in a single program over three years — it was also failing at a more basic level: the page, which gates every other action on the platform until it loads, was taking 15–20 seconds to open.

The legacy AngularJS contract dashboard, pre-rebuild
Beforefig.00The legacy AngularJS dashboard — 15–20s to load, Bootstrap 3.4.1, built for a fraction of the data it was now serving.
The real question

Delivering what T-Mobile had paid for meant deciding how to rebuild the foundation underneath it — not just designing two new features.

Deciding to rebuild, not patch

Three pressures pointed at the same answer

Any one of these might have justified a smaller patch. Together, they made the case:

  1. A paid feature commitment. Advanced search and saved views couldn't be bolted onto the legacy page's architecture.
  2. Security debt. The page ran on AngularJS (now unsupported, a security liability) with legacy Bootstrap 3.4.1 components that needed removal.
  3. Performance at scale. The join-heavy legacy architecture couldn't handle large programs' data volume.

So the real decision wasn't "should we rebuild" — it was "given that we have to rebuild, what's the most optimized foundation to build the paid features on."

Diagnosis

Tracing the slowness to the data architecture

Working with engineering, I traced the slowness to the data model. Each contract's live status was assembled by joining across many separate tables in real time — even for just the first 100 contracts on initial load. As columns and live data points were added over the years, join complexity grew, but the schema never changed to accommodate it.

The initial fix was moving contract data into OpenSearch, decoupling reads from the expensive joins. That surfaced a harder problem.

The hardest problem

Keeping 70 data points in sync

Moving to OpenSearch solved the join problem but introduced a new one — the index quickly went stale, with no pipeline keeping it current. Users would often see outdated contract data on load.

Fixing this meant mapping every single action, anywhere on the platform, that could change any of the 70 data points shown on this page. I went through the platform action by action — status changes, supplier assignments, date edits, cancellations, line item updates, and more — and catalogued which fields each one touched. That map became the spec for a real-time sync pipeline (built with Kafka) feeding OpenSearch.

The actual hard part

Not the performance tuning. The exhaustive, systems-level audit of every write path in the platform — that's what made the OpenSearch move actually work.

Execution

Shipped in ~2.5 months, while running two other squads

I ran this as PM for a three-person senior engineering team (one full-stack, one backend, one frontend) over roughly two and a half months, while continuing to manage other products in parallel. Resourcing wasn't a hard sell — since this delivered a feature T-Mobile had already paid for, the business case was largely made for us.

My scope covered diagnosis, prioritization, and spec-writing for the rebuild; sprint management across the project; and end-to-end QA — verifying not just functionality, but that performance held under load and that no contract data was lost or misrepresented in the new system.

Fixes shipped:

Advanced condition-based search inside the contract dashboard
fig.02Advanced condition-based search — one of the two paid features that drove the rebuild.
Saved views feature with multiple user-created views
fig.03Saved views — averaged 2.6 per user post-launch, a real adoption signal.
Bulk actions menu on the contract dashboard
fig.04Bulk actions — date updates, supplier assignment, cancellations, PO downloads, and more, across many contracts at once.
Managing rollout risk

Replacing the platform's entry point, live

Replacing the entry point for millions of contracts carried real risk. That shaped how we shipped it:

The bet

No dual-run period. One overnight cutover, rollback plan on standby. Cutover held.

Results

The numbers that moved

3–4.5s
page load, down from 15–20s (~75–80% reduction)
93%
avg user satisfaction across the full redesign
2.6
saved views created per user, on average
What I'd do differently

Default to active contracts, not full history

The page still defaults to loading the full contract history — including dormant contracts three-plus years old — rather than active contracts only. For a client like T-Mobile, that means computing over 2.3 million rows on every load when the vast majority aren't relevant to daily work.

I haven't yet made the case to T-Mobile for defaulting to active-only views, but it's the next obvious optimization — both for user experience and for reducing the computation cost we solved so much of the rest of this project to fix.

← Back to all work Next: AI duplicate detection →