Case Study

Dashboard Performance Optimization

Eliminated main-thread blocking in a data-heavy analytics dashboard rendering thousands of rows and real-time updates.

Result-41% time to interactive, interactions under 200ms

The dashboard rendered 5,000+ rows in a single unvirtualised component tree. Initial load blocked the main thread for over 3 seconds. Sorting or filtering triggered full re-renders, making the interface feel broken. Users had started reporting the dashboard as unusable on lower-end hardware.

Profiled the component tree with Vue DevTools and Chrome Performance panel before touching any code. Identified three root causes: unvirtualised list rendering, unnecessary computed re-evaluations on unrelated state changes, and synchronous data transforms running on the main thread. Fixed in order of impact.

  • Frontend: Vue 3 with targeted, measured performance changes
  • List rendering: Virtual scrolling via vue-virtual-scroller
  • Data processing: Web Worker handling sort and filter transforms
  • State: Computed properties with explicit, narrow dependency tracking
  • Code splitting: Chart components loaded with defineAsyncComponent

Virtual scrolling only where it measured

Not every list needed virtualisation. Applied it only to tables exceeding 500 rows after profiling. Avoided adding abstraction complexity where the performance gain was negligible.

Web Worker for data transforms

Moving filter and sort logic off the main thread eliminated UI jank during heavy operations. Workers communicated via structured clone — no shared-state race conditions.

Code-split chart components

Chart libraries accounted for a large share of the initial bundle. Lazy loading them reduced bundle size by 34% and directly improved TTI.

Profile first, optimise second

Every change was preceded by a measurement. This prevented wasted effort on already-fast components and kept the diff small, reviewable, and easy to revert.

Time to Interactive dropped 41%. Main thread blocking during interactions went from 3s+ to under 200ms. User-reported freezing complaints stopped after the first deployment. Dashboard now handles 10,000+ rows without degradation.

Vue 3TypeScriptvue-virtual-scrollerWeb WorkersChart.js
  • Move real-time data to a WebSocket connection for lower latency updates
  • Add server-side pagination to reduce initial data payload on slow connections

Like what you see?

Let's build something together.

Get in touch