What a mature insurance platform taught me about accessibility, modernization, technical debt, and knowing when not to rewrite the software
LifePRO taught me to become suspicious of obvious solutions.
Not because obvious solutions are always wrong.
Because in a mature application, the place where a problem becomes visible may be several architectural layers away from the place that actually caused it.
I joined EXL as a Senior Web Designer. LifePRO was already a substantial enterprise life-insurance application. It had customers, established workflows, an Angular front end, shared components, Bootstrap, Sass, PrimeNG, generated markup, distributed development, and years of decisions that had accumulated before I ever opened the code.
My job was ostensibly UX.
It didn't stay inside that boundary for very long.
The Airplane Was Already Flying
There is a fundamental difference between designing a new product and changing a mature enterprise system.
With a new product, you can ask:
"What should we build?"
With an established product, there's always another question:
"What can we safely change without breaking everything that already works?"
LifePRO couldn't stop being an insurance platform while we improved its user experience.
Customers still needed it. Releases still had to ship. Developers still had features to implement. Existing workflows still mattered.
So every improvement existed inside constraints.
That made understanding the implementation unusually important for a UX role.
I wasn't interested only in whether a screen looked correct.
I wanted to know why it behaved the way it did.
The Accessibility Problem Appeared Early
I began encountering accessibility problems very early in my tenure.
Some were easy to recognize at the interface.
But repeated patterns suggested that what we were seeing wasn't simply a collection of unrelated defects.
LifePRO used shared components and generated interface structures. If the same inaccessible behavior appeared again and again, there were two possibilities.
We had hundreds of independent mistakes.
Or we had a smaller number of mistakes being reproduced hundreds of times.
The second possibility was much more interesting.
Later, when VA Section 508 requirements increased the importance of formal remediation, those early observations became valuable.
We needed to make the application more accessible.
The question was how.
Then Somebody Put 1.5 Million Lines of HTML on the Table
One remediation direction would have required touching approximately 1.5 million lines of generated HTML.
That's the kind of number that should make an engineer uncomfortable.
Not because large changes are inherently wrong.
Because the size of the proposed solution was wildly disproportionate to the conceptual size of the problem.
If the same change needs to be made a million times, I want to know what generated those million instances.
So I started asking a different question.
Not:
"How do we change all this HTML?"
But:
"Why does all this HTML need the same change?"
That distinction changed the problem.
Moving Upstream
I traced the behavior back through the presentation architecture.
The repeated markup was where the accessibility problem appeared.
It wasn't necessarily where the solution belonged.
I found a way to address the behavior systematically through Sass and personally implemented the solution in approximately 150 lines.
Now we had two numbers:
~1,500,000 lines of generated HTML
versus
~150 lines of Sass
The arithmetic is fun—roughly four orders of magnitude—but that isn't why the smaller solution mattered.
Every line you change creates responsibility.
It can regress.
It can diverge.
It has to be understood later.
It may have to be changed again.
Avoiding the markup rewrite meant avoiding an enormous new surface of future responsibility.
The best part of those 150 lines wasn't what they added.
It was what they allowed us not to change.
PrimeNG Reinforced the Lesson
The same principle appeared elsewhere.
LifePRO depended on PrimeNG components.
A shared component library is leverage: build behavior once and reuse it throughout the application.
But leverage works in both directions.
If the shared behavior is wrong, you can reproduce the wrong thing everywhere too.
That made accessibility work at the component layer particularly important.
Where possible, I investigated the shared implementation and styling behavior—including working with a local/internal PrimeNG fork or copy and Sass—rather than accepting repeated screen-level remediation as the default strategy.
The lesson was becoming consistent:
Repeated symptoms deserve an upstream investigation.
Then I Asked a Different Annoying Question
LifePRO was running Angular 7.
Why?
There are plenty of reasons an enterprise application stays on an older framework version, and "the developers don't know how to upgrade it" is rarely a useful assumption.
So rather than argue abstractly about whether LifePRO could move forward, I made myself a fork and tried it.
I upgraded my LifePRO branch from Angular 7 to Angular 10.
And it worked.
Sort of.
Which was much more useful than either "yes" or "no."
We Didn't Really Have an Angular Problem
Getting Angular forward demonstrated that the framework version itself wasn't the entire blocker.
The experiment exposed surrounding problems in the application's Bootstrap/Sass architecture and related front-end dependencies.
That changed the modernization question.
Before the experiment, the visible problem was:
LifePRO is on Angular 7.
Afterward, the better description was:
LifePRO has accumulated front-end architectural dependencies that make an Angular upgrade more expensive than changing Angular itself.
That's useful information.
It also isn't a fairy-tale ending.
Production did not move to Angular 10 while I was there.
LifePRO was still on Angular 7 when I left.
The surrounding architecture required broader work, much of it rooted in decisions that predated my employment, and the organization had not undertaken that complete modernization during my tenure.
My fork didn't solve production modernization.
It did something else valuable:
It turned an assumption into evidence and showed us where the real work was.
Success and Failure Aren't Binary
Those two experiences—the accessibility remediation and Angular modernization—look very different if success is defined only as "did the whole thing ship?"
The Sass intervention had a problem we could move upstream and solve economically.
We did.
The Angular experiment moved upstream and uncovered a larger problem.
We couldn't responsibly solve all of that within the existing scope.
So we didn't pretend otherwise.
Both outcomes improved our understanding of the system.
That's one of the lessons mature products teach you.
Sometimes success is shipping the fix.
Sometimes success is discovering that the proposed fix attacks the wrong layer.
And sometimes success is proving that the thing everyone calls the problem is actually just the first visible symptom of a larger one.
Meanwhile, We Still Had a Product to Build
None of this happened in isolation.
While investigating architecture and accessibility, I was also doing the ordinary work I had actually been hired to do.
Across LifePRO versions 20 and 21, I designed approximately 40% of the screens and workflows.
I worked in tools including Figma and Justinmind.
I worked with developers in Noida to translate designs into production interfaces.
And that day-to-day implementation work continuously fed information back into the architectural work.
A design might expose a limitation in a component.
A component might expose a styling problem.
A styling problem might reveal technical debt.
Technical debt might constrain the next design.
UX and engineering weren't sequential activities.
They were a feedback loop.
Distributed Development Made Precision Matter
Working with a development team thousands of miles away magnifies ambiguity.
A design handed over without enough behavioral context can become something different during implementation.
A bug report saying "this doesn't look right" isn't particularly useful either.
Because I could work in both design and implementation, I could communicate the problem more precisely.
Sometimes the conversation was about user intent.
Sometimes it was about Angular.
Sometimes PrimeNG.
Sometimes HTML or Sass.
Sometimes it was about why the technically easiest implementation wasn't the best long-term choice.
That ability to cross the boundary reduced the amount of translation required between the people deciding what the experience should be and the people making it real.
The Same Translation Was Necessary Upward
Technical detail isn't equally useful to every audience.
A developer may need to understand exactly how the Sass works.
An executive probably doesn't.
But an executive can understand the difference between:
changing roughly 1.5 million lines of generated output
and
correcting the shared behavior responsible for producing the problem.
Part of navigating LifePRO was learning to explain the same underlying issue at the appropriate level.
I worked across development, product, senior vice presidents, and technical leadership within the larger CTO/CEO structure.
The problem didn't change depending on the audience.
The language used to explain its consequences did.
What Went Right
We shipped substantial UX work across LifePRO v20 and v21.
I contributed approximately 40% of those screens and workflows.
We found accessibility problems that could be addressed systemically.
We avoided an enormous generated-markup remediation by finding a much smaller solution at the appropriate architectural layer.
We used shared component and Sass thinking to reduce repeated fixes.
And the Angular fork demonstrated that the framework itself could move forward.
What Didn't
Not every architectural problem could be fixed within the scope available to us.
LifePRO's production application remained on Angular 7.
The modernization experiment exposed Bootstrap, Sass, dependency, and broader front-end architectural debt that required more extensive remediation than simply upgrading Angular.
Some of those conditions were the product of decisions made years before I joined the team.
Knowing what needed to change did not automatically create the organizational scope required to change it.
That distinction matters.
Technical discovery and organizational capacity are two different things.
How We Navigated It
We learned to separate problems into categories.
Problems we could fix safely now.
Fix them.
Problems whose proposed solution attacked the wrong layer.
Challenge the premise and move upstream.
Problems that required architectural investment beyond the current scope.
Investigate them, demonstrate the path, document what blocks it, and don't pretend an experiment is a production migration.
That approach let us continue improving the product without requiring LifePRO to become a different application before progress could occur.
The Lesson I Kept
I entered EXL with the title Senior Web Designer.
I left with a much clearer understanding of the kind of work I was actually best at.
It lives between disciplines.
UX tells me where the person encounters the problem.
Front-end engineering lets me follow that problem into the implementation.
Accessibility forces me to ask whether the interface works for everyone.
Architecture forces me to ask whether we're correcting the cause or multiplying another workaround.
And experimentation gives me a way to replace arguments with evidence.
The 1.5 million lines weren't really the story.
Neither were the 150.
The story was learning to ask:
"Where does this problem actually belong?"
That question saved us from one enormous rewrite.
On another problem, it revealed work we weren't yet ready to undertake.
Both answers were useful.
And that is probably the most durable thing LifePRO taught me.

