Almost every team agrees performance matters. Almost no team has a mechanism that keeps it from regressing. The gap is not intent; it is enforcement. Performance treated as a QA checklist is discovered late, argued about subjectively, and fixed reluctantly.
Treat it as a constraint instead — like type safety or a test suite — and it starts to hold.
Set a budget in numbers
Pick explicit thresholds and write them down:
- Largest Contentful Paint under 1.5s on a mid-tier mobile device.
- Cumulative Layout Shift under 0.05.
- Total client JavaScript under a defined kilobyte ceiling per route.
- Interaction latency under 200ms for primary controls.
The exact numbers matter less than their existence. A budget turns “this feels slow” into “this route exceeds its JavaScript budget by 42 kilobytes.”
Enforce it in continuous integration
A budget checked manually is a budget that erodes. Wire it into CI:
- Run Lighthouse CI on representative routes for every pull request.
- Fail the build when a threshold is exceeded, or flag it clearly on the pull request.
- Track bundle size per route and diff it against the base branch.
The first time a build fails because a dependency added 30 kilobytes, the team learns the constraint is real. That single failure teaches more than a style guide.
Make the default path the fast path
Performance is mostly decided by architecture, not micro-optimisation:
- Ship HTML first. Server-render content so the primary paint does not wait on JavaScript.
- Hydrate only what is interactive. Static content should never ship client-side framework code.
- Defer below-the-fold work. Load non-critical islands when they become visible.
- Optimise images at build time. Correct dimensions, modern formats, and explicit width and height to prevent layout shift.
- Subset and self-host fonts. Eliminate render-blocking third-party font requests.
If the convenient choice is the slow choice, the slow choice wins every sprint. Change the default.
Respect users who opt out of motion
Every animation needs a prefers-reduced-motion fallback — a static state, not merely a shorter animation. This is an accessibility requirement and, in practice, a reminder that motion should be an enhancement layered on top of a fully functional page.
Own it together
Assign a named owner for the performance budget per surface, and review the trend in the same ritual as incident reviews. When a regression ships, ask what mechanism allowed it, not who caused it.
Performance is not a launch milestone. It is a property of the system that decays unless something holds it in place. CI is that something.