Web · 4 min read

The five expensive habits killing your web app's speed

By the Imustech web engineering team · Updated December 2025

Web performance

Whenever we inherit a codebase, we run the same one-week performance audit before we ship a single feature. In eight out of ten cases we recover 40% or more of Time-to-Interactive in that first week — often without any real refactor. Here are the five habits we look for first.

1. Everything imported everywhere.

Node modules pulled into the client bundle: `lodash`, `moment`, entire UI libraries, tree-shakeable icon packs that never got tree-shaken. Symptom: a `main.js` bundle over 500 KB gzipped. Fix: run `npm-check`, replace `moment` with `date-fns` or `dayjs`, migrate icons to on-demand imports. Cost: a day. Reward: 200–400 ms of TTI.

The single fastest way to slow a web app down is to say "yes" to every npm package a developer suggests. The second is to say "yes" to every dashboard chart library.

2. Server-rendering things that should be static.

Marketing pages, docs, product landing pages hitting a full SSR render on every visit. Every one of these should be either statically generated (SSG) or incremental static regeneration (ISR). Fix: identify pages that don't need per-request data and shift them to `getStaticProps`, `generateStaticParams` or your framework's equivalent.

3. The infinite waterfall on first load.

User lands on the homepage. Browser requests HTML → HTML requests JS → JS requests API → API triggers a second API → second API needs auth → auth roundtrip. Six sequential hops. Fix: preload critical data on the server, hydrate the client with it, and never let auth be more than one round-trip.

4. Images without discipline.

Full-resolution 4000×3000 JPGs served to phones. No `srcset`. No lazy-loading. No modern format (AVIF/WebP). This is the single biggest LCP killer we see. Fix: use your framework's image component (Next.js `Image`, Nuxt `NuxtImg`), set explicit sizes, and serve modern formats.

5. Blocking third-party scripts loaded synchronously.

Marketing loaded a chat widget, an analytics tool, an experimentation platform and a heat-mapper. All synchronous. All in `<head>`. Cumulative cost: 1.5 seconds of TTI. Fix: audit every third-party. Load asynchronously with `defer`, or better, only after user interaction. Kill the ones no-one has looked at in a year.

The one-week audit

The result

A tangible LCP drop, a smaller bundle, a cleaner network waterfall — usually delivered before you've had time to argue about whether to migrate off React. Do this audit before you do anything ambitious. It changes the conversation.

Want us to run this audit for you?

Fixed-fee, one week, keep the report.

We audit, prioritise and ship the top wins — with a written report you keep, whether or not we work together afterwards.

Book a performance audit