Finding Bottlenecks in the Frontend to Optimize the UX
This is a common interview discussion topic that gives you the opportunity to demonstrate how you tackle new codebases.

“You haven’t seen our codebase yet. What are the first things you’d look at to improve performance, without touching the backend?”
Imagine you're asked that in one of your final rounds of interviews 👆. How would you reply?
In an interview setting, you are not working with real data but with assumptions. You need to demonstrate you know where to look and what the most likely culprits could be.
Here's a useful template/flow I've created for myself:
My first step wouldn’t be to open the code editor; it would be to measure what users actually experience. Then I’d move layer by layer from what the user experiences 👉🏼 what the framework manages 👉🏼 how the data flows.
What Users actually experience
I’d open the app, record the First Contentful Paint (FCP) and Largest Contentful Paint (LCP) using Chrome DevTools or Lighthouse. These two metrics tell me when users start seeing real content and when the page feels ready.
Are those numbers high? The probable culprits are:
Likely Culprits
Heavy Bundles
Blocking Scripts
Unoptimized images
Possible Fixes:
Code-splitting at the route level
Lazy-loading heavy components
Removing unnecessary work when your component mounts (depends on the lifecycle of your specific framework).
State Management
Once the user-facing metrics have been identified, I’d move inward and check the state management tool of choice or approach.
Likely Culprits:
Is there data that belongs to a single page or component but has been put in a store or global state?
Re-renders that are happening due to state not being where it should be.
Unnecessary Network requests caused by those re-renders.
Possible Fix:
- Where possible, make the move to the local component state. That change alone can drastically reduce re-renders and make the UI feel snappier.
Side Effect Hygiene
This is where a lot of invisible slowdowns hide.
In frontend apps (like Vue), side effects are anything that happens outside the reactive system. Things like event listeners, timers, API requests, or websockets. If they aren’t cleaned up properly, they keep running even after components are unmounted, leading to:
Redundant fetches
Memory leaks
Updates on destroyed components.
Likely Culprits:
Fetch calls triggered from multiple components (when a user navigates away before a fetch finishes, but the old request is still ongoing, and tries to update the state)
Event listeners added but never removed
Intervals or timeouts that are not cleared on unmount
Websocket or subscription connections left open
Possible Fixes:
Use a centralized fetch pattern, like TanStack Query (if multiple components request the same data, it only fetches once and then shares the result).
Always clean up when unmounting: remove listeners, clear intervals, and close sockets.
Debounce or throttle frequent events (scroll, resize, input).
The key here is prioritization. Start from the user’s perception of performance (FCP/LCP), then address reactivity and state, then side effects and cleanup. Each layer matters for the next, and every fix compounds.
This template has worked several times for me because it shows that I don’t want to optimize just for the sake of optimization or for hypothetical scenarios that might never happen. I’m aligning technical decisions with how users actually experience the product.



