DEV Community

Daniel Kuboi
Daniel Kuboi

Posted on

Speed is also a Feature

Modern web applications are more powerful than ever. Frameworks keep evolving, AI can generate code in seconds, and developers can ship features faster than at any other point in history. Yet despite all this progress, many applications still feel frustratingly slow. We've all experienced it. You click a link and stare at a blank screen. You press a button and wonder whether it actually worked. You try to scroll, but the page stutters and freezes. At that moment, users aren't thinking about your architecture, design patterns, or technology stack. They're thinking about one thing:

"Why is this so slow?"
That's why performance isn't just a technical concern. It's a product feature.

Users may never notice a well-designed database schema or a carefully structured codebase, but they immediately notice when an application feels fast. Speed creates confidence. It makes software feel reliable, polished, and trustworthy.

In many cases, speed is the very first feature users experience.

This article explores web performance from the user's perspective. We'll look at how people perceive speed, learn how modern performance metrics measure real-world experiences, understand the RAIL model, and discuss practical techniques for building applications that feel fast on every device and network.

Why Performance Matters
Performance is often discussed as a technical metric, but at its core, it's about people.

When users visit your application, they're trying to accomplish something. Maybe they're shopping online, reading an article, sending a message, or managing their finances. They don't care how many microservices are running behind the scenes. They care about completing their task quickly and without frustration.

Research has consistently shown that delays have a direct impact on user behavior. The longer people wait, the more likely they are to leave.

Human perception generally follows these patterns:

0–100 ms Feels instant Around 1 second Delay is noticeable but doesn't interrupt

2–5 seconds Patience starts to wear thin

5–10 seconds Users begin questioning
More than 10 seconds Many users abandon the task altogether

Think about your own browsing habits. If an online store takes ten seconds to load a product page, chances are you'll open another tab and look elsewhere. Users don't compare your application against technical benchmarks. They compare it against their expectations. And expectations keep getting higher.

Performance Through the User's Eyes

One of the biggest mistakes developers make is measuring performance differently from how users experience it.

Imagine a page that displays content after two seconds but remains unresponsive until ten seconds because JavaScript is still executing in the background.

From an engineering perspective, the page loaded.

From the user's perspective, it's broken.

This is why modern web performance focuses on user experience rather than purely technical measurements.

When I evaluate a website's performance, I typically ask four simple questions:

  1. Is something happening?
  2. Is the content useful?
  3. Can I interact with it?
  4. Does everything feel smooth?

These questions map closely to the way users naturally experience a page as it loads.

1. Is Something Happening?
The first thing users want is reassurance. Nobody likes staring at a blank screen. As soon as someone visits a page, they want evidence that the application is working.

Time to First Byte (TTFB)

TTFB measures how long it takes for the browser to receive the first response from the server.

A slow TTFB often points to backend issues such as:

  1. Expensive database queries
  2. Poor caching strategies
  3. Slow APIs
  4. Network latency
@GetMapping("/products")
public List<Product> getProducts() {
    return productRepository.findAll();
}
Enter fullscreen mode Exit fullscreen mode

This looks harmless, but if it triggers multiple database joins or returns thousands of records, response times can increase dramatically. Often, improving performance isn't about adding more servers. It's about removing unnecessary work.
First Paint measures the moment something appears on the screen.

Even if it's just a loading skeleton or navigation bar, users gain confidence because they can see progress. A blank page creates uncertainty. Visible feedback creates trust.

2. Is It Useful?
Showing something quickly is good. Showing meaningful content quickly is better. Users don't visit a website to admire loading indicators. They come for content.

First Contentful Paint (FCP)
FCP measures when meaningful content first appears.
This could be:

  1. Text
  2. Images
  3. Icons
  4. Headlines

At this point, users can begin consuming information.

Largest Contentful Paint (LCP)
LCP measures when the largest visible element appears on screen.In many applications, that's the content users care about most.
Examples include:

  1. A hero image
  2. A product photo
  3. A blog article
  4. A dashboard summary

Google recommends keeping LCP under 2.5 seconds.
A common mistake is loading oversized images:

<img src="huge-image.jpg">
Enter fullscreen mode Exit fullscreen mode

A better approach is to compress assets and use modern formats:

<img
    src="hero.webp"
    width="1200"
    height="600"
>
Enter fullscreen mode Exit fullscreen mode

3. Is It Usable?
Many modern websites look loaded long before they're actually usable.The page appears complete, but clicks don't work.

Buttons feel delayed.
Scrolling becomes sluggish.

This often happens because JavaScript is still busy executing.

Time to Interactive (TTI)
TTI measures when users can reliably interact with the page. A fast-loading page that doesn't respond is still a poor experience.

Interaction to Next Paint (INP)
INP focuses on responsiveness.
It measures how quickly the browser reacts after a user interaction.

For example:

  1. Clicking a button
  2. Opening a menu
  3. Submitting a form

When interactions feel delayed, users notice immediately.
Consider this example:

button.addEventListener("click", () => {
    performMassiveCalculation();
});
Enter fullscreen mode Exit fullscreen mode

If that calculation blocks the main thread for several seconds, the application feels frozen.
A better option could be:

button.addEventListener("click", () => {
    showLoadingIndicator();

    setTimeout(() => {
        performMassiveCalculation();
    }, 0);
});
Enter fullscreen mode Exit fullscreen mode

4. Does It Feel Smooth?
Performance doesn't end once a page loads. Users continue judging your application during scrolling, navigation, and animations.
Small annoyances accumulate quickly.

Cumulative Layout Shift (CLS)
Have you ever tried clicking a button only for the page to suddenly move? That's layout shift.

It's one of the most frustrating performance problems because it interrupts user actions.

A common cause is images loading without reserved dimensions:

<img src="banner.jpg">
Enter fullscreen mode Exit fullscreen mode

A better approach is:

<img
    src="banner.jpg"
    width="1200"
    height="400"
>
Enter fullscreen mode Exit fullscreen mode

Frame Rate
Smooth interfaces generally run at 60 frames per second. That means the browser has roughly 16 milliseconds to render each frame.

Whenever rendering exceeds that budget, users experience:

  1. Stuttering animations
  2. Choppy scrolling
  3. Laggy interactions

The RAIL Model
Google introduced the RAIL model as a way to think about performance from a human perspective rather than a technical one.
RAIL stands for:

  1. Response
  2. Animation
  3. Idle
  4. Load

Each category represents a different part of the user experience.

Response
Users expect feedback almost instantly. If someone clicks a button, they shouldn't wonder whether the click was registered.

A simple loading state often improves perceived performance significantly.

submitButton.onclick = () => {
    showSpinner();
    submitForm();
};
Enter fullscreen mode Exit fullscreen mode

Even when the request takes several seconds, users feel more comfortable because the application is communicating.

Animation
Smooth animations make interfaces feel alive. Poor animations make them feel broken. Whenever possible, animations should remain close to 60 FPS.

For example, avoid expensive calculations during scroll events:

window.addEventListener("scroll", () => {
    expensiveCalculation();
});
Enter fullscreen mode Exit fullscreen mode

Instead, allow the browser to optimize rendering:

window.addEventListener("scroll", () => {
    requestAnimationFrame(updateUI);
});
Enter fullscreen mode Exit fullscreen mode

Idle
Every application has moments when users aren't interacting. These moments are opportunities. Background tasks such as preloading data or caching assets can be performed during idle periods.

requestIdleCallback(() => {
    preloadNextPage();
});
Enter fullscreen mode Exit fullscreen mode

Load
Performance isn't about loading every resource immediately. It's about loading the right resources first.
Techniques such as:

  1. Code splitting
  2. Lazy loading
  3. Server-side rendering
  4. Asset compression
  5. CDN caching

help prioritize what users actually need.

In conclusion Users don't experience your codebase. They experience its speed. They don't see your microservices, design patterns, cloud infrastructure, or database indexes. They see how quickly content appears, how responsive interactions feel, and whether the application helps them accomplish their goals without friction.

Top comments (0)