
5 Frontend Performance Patterns Every Developer Should Know
When you use GitHub, Slack, or ChatGPT, they don't feel slow. You click, and something happens immediately. You type, and the interface responds. You hit save, and it's done. No spinners. No waiting.
This isn't because their servers are magical. It's because modern frontend applications have learned to hide latency.
The bottleneck isn't your server—it's the network. Most of the time in a user interaction is spent waiting for data to travel to and from the server. The best frontend developers don't fight this reality. They work around it using five patterns you'll see in every modern web application.
A frontend developer can't make the network faster. But they can architect the interface to feel responsive despite the network's slowness.
Modern applications do this by mastering five patterns that every developer should recognize and understand when to use.
1. Request Deduplication
What it is: When multiple parts of your application request the same data, only send one request. Share the response with everyone who asked.
The problem: Imagine you open a dashboard. Five different components all need the user's profile information. Without deduplication, the browser sends five identical requests to the server.
Real-world:
- Open any GitHub page with multiple components showing your avatar and name
- Load a Slack workspace where the current user info is displayed in the header, sidebar, and profile menu
- React Query automatically deduplicates requests—if two components ask for the same data within the same render cycle, it sends one request and gives both the same response
Why it matters: Five requests that could be one. For high-traffic applications, this is the difference between sustainable systems and ones that collapse under load.
2. Optimistic Updates
What it is: Update the UI immediately when a user takes an action, before waiting for the server to confirm it actually worked.
The problem: When you like a post on Twitter, the traditional flow would be: send request → wait 200ms → server confirms → update heart to red. The user sees a delay.
Real-world:
- Like button on Twitter/X: Heart turns red instantly. Server catches up in the background.
- Todo apps: You type a task and hit enter. It appears in your list immediately, gets sent to the server, and if it fails, disappears.
- Gmail: Archive an email and it vanishes from your inbox instantly. The server confirms later.
- Slack reactions: Add a reaction to a message and it shows up immediately.
The key: if the server says "no, that failed," the UI reverts and shows an error.
Why it matters: Users feel like the app responds instantly to their actions instead of waiting for the network.
Read more
3. Streaming UI
What it is: Instead of waiting for a complete response, the server sends data in chunks as it's generated. The UI updates progressively as chunks arrive.
The problem: Some operations take time—AI generating text, querying large datasets, processing complex reports. If the server waits to send everything at once, the user stares at a spinner for 8 seconds. Then suddenly everything appears.
Real-world:
- ChatGPT and Claude: Text appears word-by-word as the AI generates it. You see something happening immediately, not a blank screen for 8 seconds.
- AI code generation tools: Suggestions appear line-by-line as the model generates them.
- CI/CD pipeline logs: Each log line appears as it's generated, not all at once when the pipeline completes.
- Search results: The first results appear immediately while the backend is still searching for more.
Why it matters: Users get feedback that something is happening instead of waiting in silence. Reduces perceived wait time dramatically.
Read more
4. Stale While Revalidate
What it is: Show the user cached data immediately (even if it's old), then quietly fetch fresh data in the background and update the UI when it arrives.
The problem: There's a trade-off between speed and freshness. Show cached data instantly but it might be outdated. Or always request fresh data but users wait. Stale While Revalidate does both.
Real-world:
- GitHub notifications: Shows your notification count instantly (might be from 30 seconds ago), fetches the latest count silently in the background.
- Dashboard statistics: Display the last-known values immediately. While the user is looking at it, fresh numbers arrive and update quietly.
- Gmail: Shows your last-synced email list, pulls new emails in the background.
- Social media feeds: Shows the posts you've already seen while loading new ones.
The user gets instant feedback and reasonably fresh data without forcing them to wait.
Why it matters: Eliminates the "wait or be stale" choice. Users get both speed and freshness.
Read more
5. Smart Polling
What it is: Instead of asking the server for updates blindly every 5 seconds, polling adapts based on context—pause when the tab is hidden, stop when offline, slow down when the user is idle.
The problem: Blind polling wastes resources. If a notification badge checks for updates every 5 seconds even when the user isn't looking at the page, even when they're offline, or hasn't moved their mouse in 30 minutes—you're burning battery and hammering the server for no reason.
Real-world:
- Notification badges: Poll frequently when the user is looking at the tab. Pause when they switch to another tab. Resume immediately when they switch back.
- Live activity feeds: Check for new activities when the user is active. Slow down polling when idle for 10+ minutes.
- Collaborative editing: Poll to see if other users are typing. Stop polling when the browser goes offline.
- Email clients: Check for new messages periodically, but intelligently—not blindly every 5 seconds forever.
The "smart" part means the application understands context instead of just following a fixed schedule.
Why it matters: Reduces server load, saves battery on mobile, and only checks for updates when users actually care.
They All Answer the Same Question
Notice what these patterns have in common? They all solve the same fundamental problem:
How do we make the UI feel fast despite slow or unreliable networks?
They don't make your server faster. They don't improve network infrastructure. Instead, they make your application feel faster by:
- Reducing unnecessary work (request dedup)
- Responding immediately to user actions (optimistic updates)
- Showing progress instead of waiting (streaming)
- Giving instant results and refreshing quietly (stale while revalidate)
- Being smart about when to check for updates (smart polling)
The Difference Between "Works" and "Feels Good"
A basic application: fetch data → wait → render. It works.
A modern application uses these patterns to eliminate waiting. It responds to clicks instantly. It shows old data while fetching new data. It streams responses instead of blanking the screen. It knows when to stop polling to save battery.
Most modern libraries handle these patterns automatically. React Query, SWR, and TanStack Router implement most of these behind the scenes. But understanding what problem each pattern solves is the difference between building an app that functions and one that feels polished.
Resources
- MDN: HTTP Caching — Comprehensive guide to HTTP cache headers and stale-while-revalidate
- MDN: Fetch API — Understanding network requests and response handling
- React Query Documentation — Library that implements request deduplication, caching, and background revalidation automatically
- MDN: Server-Sent Events (Streaming) — Technical foundation for streaming responses
- SWR by Vercel — Data fetching library implementing stale-while-revalidate patterns



