Why I care about web performance
A fast website is not a luxury. It is the baseline. Every 100ms of additional load time costs engagement. Users do not wait. They leave, and they do not come back.
I started caring about performance after running Lighthouse on a project I thought was well-built and getting a score of 38. That was humbling.
The metrics that matter
Largest Contentful Paint (LCP). How long until the main content is visible. Target: under 2.5 seconds. This is the metric users feel most directly. If the hero section takes 4 seconds to appear, the page feels broken.
First Input Delay (FID) / Interaction to Next Paint (INP). How long until the page responds to user interaction. Target: under 200ms. A button that takes 500ms to respond after clicking feels laggy regardless of how fast the page loaded.
Cumulative Layout Shift (CLS). How much the page layout moves around as it loads. Target: under 0.1. When text shifts down because an image loaded above it, that is layout shift. It is disorienting and makes users click the wrong thing.
Quick wins
Optimize images. This alone can cut load times in half. Use modern formats (WebP, AVIF), serve appropriate sizes for the viewport, and lazy-load images below the fold.
// Next.js handles this automatically
import Image from "next/image";
<Image
src="/photo.jpg"
alt="Description"
width={800}
height={600}
loading="lazy"
/>Reduce JavaScript. Every kilobyte of JavaScript needs to be downloaded, parsed, and executed. Audit your bundle with tools like next build --analyze or source-map-explorer. Remove unused dependencies. Code-split by route.
Use system fonts or font-display: swap. Custom fonts block rendering. Using font-display: swap shows fallback text immediately while the custom font loads. On this site, DM Sans loads with swap so the page is readable instantly.
Cache aggressively. Static assets (images, CSS, JS bundles with hashed filenames) should have long cache headers. The browser stores them locally and does not re-download them on repeat visits.
Measuring performance
Lighthouse in Chrome DevTools gives you a quick audit with specific recommendations. Run it in incognito mode (extensions affect results) and test on a simulated slow connection.
PageSpeed Insights tests from Google's servers, which gives you field data from real users alongside lab measurements.
Web Vitals can be instrumented in your application to collect real user metrics:
import { onCLS, onINP, onLCP } from "web-vitals";
onCLS(console.log);
onINP(console.log);
onLCP(console.log);Framework choices affect performance
This site is built with Next.js, which handles a lot of performance optimization automatically: code splitting by route, image optimization, font optimization, and static generation. Choosing a framework that handles these things well saves you from solving them manually.
If your framework makes it hard to ship a fast page, the framework is working against you.
The mindset
Performance is not something you fix once. It is a constraint you design within. Every dependency you add, every image you include, every animation you create has a cost. The question is always: does the user value what this costs them in load time?
Most of the time, the answer is simpler than you think. Fewer dependencies, optimized images, and letting the framework handle code splitting gets you 90% of the way there.
Sources
Related posts
Why I built Omnibase: a universal database MCP server
I got tired of copy-pasting query results between DataGrip and AI agents. So I built an MCP server that gives AI agents secure, direct access to any database.
Delta libraries: how diffing works and which library to use
What delta libraries do, how diff algorithms work under the hood, and a practical comparison of the most popular options in the JavaScript ecosystem.
Offline-first apps: harder than it sounds
Building apps that work without internet is one of those things that seems straightforward until you actually try it. Here is what makes it hard and how to approach it.
Enjoying the blog? Subscribe via RSS to get new posts in your reader.
Subscribe via RSS