Adaptive loading helps you maintain Core Web Vitals across varying network conditions. Learn to use the Network Information API to deliver resilient experiences.
Last month, our team spent three days chasing a mysterious LCP regression that only appeared for users on 3G and "slow 4G" connections. We realized that our heavy hero images and JS bundles were clogging the pipe, turning a snappy experience into a 6-second wait for anyone not on fiber.
We needed a way to detect those constraints in real-time and adjust our delivery accordingly. By implementing adaptive loading patterns, we transformed our page from a "one-size-fits-all" delivery model into a self-healing system that respects the user's current environment.
The foundation of our approach is the navigator.connection object. It provides a read-only interface to the user's network state. While browser support isn't universal—Safari still lags behind—it's a progressive enhancement that pays dividends for the majority of Chrome and Edge users.
Here is how we check for a "Save Data" mode or a slow connection:
JAVASCRIPTconst connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; function isSlowConnection() { if (!connection) return false; // Check for 3G or slower, or if the user explicitly requested data savings return connection.saveData || [CE9178">'slow-2g', CE9178">'2g', CE9178">'3g'].includes(connection.effectiveType); }
When isSlowConnection() returns true, we trigger a specific set of rules: we drop high-resolution images, defer non-essential third-party scripts, and pause auto-playing video.
If you treat every user as if they're on a high-speed desktop connection, you're bound to fail your Core Web Vitals. We initially tried to solve this by simply shrinking all images across the board. That was a mistake; it penalized desktop users for no reason.
Instead, we moved to a dynamic strategy where we serve smaller assets only when the network environment demands it. This is a core pillar of modern client-side performance tuning.
Before diving into complex logic, make sure you've already optimized your baseline. If you haven't mastered the basics, check out how Browser Resource Prioritization: Controlling Network Scheduling can help you manage your request queues. You should also be leveraging the Fetch Priority API: Optimize Resource Prioritization for Core Web Vitals to ensure critical assets jump the queue when bandwidth is scarce.
To make this work in production, we don't just rely on the API; we combine it with Save-Data headers and media queries.
We use the <picture> element to swap out heavy assets. If the network is slow, we serve a low-quality placeholder or a smaller crop.
HTMLstyle="color:#808080"><style="color:#4EC9B0">picture> style="color:#808080"><style="color:#4EC9B0">source media="(max-width: 799px)" srcset="hero-small.jpg"> style="color:#808080"><style="color:#4EC9B0">source media="(min-width: 800px)" srcset="hero-large.jpg"> style="color:#808080"><style="color:#4EC9B0">img src="hero-large.jpg" alt="Hero image"> style="color:#808080"></style="color:#4EC9B0">picture>
When we detect a slow network, we programmatically adjust the priority of our requests. We use a simple fetch interceptor that lowers the priority of analytics and ad scripts, reserving the limited bandwidth for the LCP element.
We hit a snag early on: we were over-engineering the client-side checks. We tried to re-fetch assets if the connection speed changed mid-session, which caused a massive jump in CPU usage and battery drain.
We learned to stick to "initial load" decisions. If the user starts on 3G, they stay on the "lite" experience for the duration of that session. Trying to swap assets live usually causes a layout shift, which destroys your CLS score.
If you're interested in how to keep the page interactive while these assets load, I've written about Data Hydration Strategies: Improving LCP and INP Performance to ensure your interactivity doesn't suffer during the transition.
Q: Is the Network Information API reliable? A: It's an estimate. It measures the effective connection type, not the actual instantaneous throughput. Use it as a hint, not a source of truth.
Q: Does this replace CDN-level optimizations? A: Absolutely not. This is a client-side layer. You should still use CDNs to cache assets and potentially use TTFB Optimization: Using Resource Hints for Connection Warming to handle the initial connection latency before your adaptive logic even kicks in.
Q: Will this hurt my SEO? A: Googlebot generally crawls from a high-speed environment. As long as your site is accessible and the "heavy" version is served to the bot, your rankings won't suffer.
We're still refining our saveData logic. Sometimes, the browser reports a "3G" connection, but the user is actually on a stable, albeit slow, link where a high-res image would have loaded fine.
Next time, I want to experiment with storing the "connection profile" in localStorage so we don't have to perform detection on every single page load. It's not a perfect science, but it’s a massive step up from ignoring the constraints of the real world. Building for adaptive loading is messy, but it's the only way to ensure your app stays usable for everyone, not just those with the latest flagship devices.
Master the Cache Storage API and Resource Timing API to control your browser resource lifecycle. Learn to optimize performance monitoring and network usage.
Read moreMaster memory management to stop garbage collection jitter and long tasks. Improve your Core Web Vitals by keeping the main thread clear and responsive.