Writing
Web Development3 min read

Frontend Performance Budgets for SaaS That Actually Stick

How to set and enforce frontend performance budgets in a SaaS product—Core Web Vitals targets, bundle limits, CI gates, and the metrics that matter.

AGAnsh GuptaFrontend Engineer
WEB

Performance is a feature, but "let's be faster" is not a plan. In a SaaS product where dashboards grow every sprint, speed erodes one innocent dependency at a time. The fix isn't heroics—it's a budget you enforce in CI so regressions get caught before they ship. Here's how I set them.

Budget the metrics users feel

Start with Core Web Vitals, because Google ranks on them and users feel them:

  • LCP (Largest Contentful Paint) — under 2.5s. The main content, not a spinner.
  • INP (Interaction to Next Paint) — under 200ms. This replaced FID and is the real measure of "does the app feel snappy?"
  • CLS (Cumulative Layout Shift) — under 0.1. Reserve space for images and async content.

These are field targets. Measure them with real-user monitoring (RUM), not just a lab run on your fast laptop.

Budget the bytes that cause them

Vitals are outcomes; bytes are the input you control. Set hard limits on the initial payload:

  • JavaScript (initial route): ~170kb gzipped is a sane ceiling for an interactive app.
  • CSS: keep it lean—Tailwind's purge should leave you well under 30kb.
  • Images: serve modern formats (AVIF/WebP), size them for the layout, and lazy-load below the fold.

Enforce it in CI, or it won't happen

A budget nobody checks is a wish. Wire it into the pipeline so a regression fails the build. Two layers work well.

Bundle size gate with size-limit:

{
  "size-limit": [
    { "path": ".next/static/chunks/main-*.js", "limit": "170 kB" }
  ]
}

Lighthouse CI for the vitals, asserting on the numbers:

// lighthouserc.js
module.exports = {
  ci: {
    assert: {
      assertions: {
        "largest-contentful-paint": ["error", { maxNumericValue: 2500 }],
        "cumulative-layout-shift": ["error", { maxNumericValue: 0.1 }],
      },
    },
  },
};

Now "it got slower" is a red check, not a vibe someone raises three releases later.

The habits that keep budgets green

  • Code-split by route and lazy-load heavy, rarely-used surfaces (charts, editors, modals).
  • Ship less JavaScript. Prefer Server Components and server-side data fetching where the framework allows.
  • Audit dependencies before adding them. A date library can cost more than the feature it enables—check the gzipped size first.
  • Defer the non-critical. Analytics, chat widgets, and feature flags should never block first paint.
  • Watch the p75, not the average. Averages hide your slowest users; the 75th percentile is what Google reports and what real people experience.

Make it cultural

The tooling is the easy 20%. The other 80% is treating a failed budget like a failed test—something you fix, not override. Put the numbers in the PR template. Celebrate when someone deletes a dependency. Once the team internalizes that fast is the baseline and slow needs justification, the budget stops being a gate and becomes how you build.

Fast products feel trustworthy. In SaaS, that trust compounds into retention—which is why performance is never just an engineering concern.

#Performance#Core Web Vitals#SaaS#Web Development#CI
AG

About Ansh

Frontend engineer with 4+ years building scalable SaaS products, design systems, CRM, analytics and omnichannel platforms.

More about me →

Related reading