Asynchronous Loading: Definition, Async vs Defer, Performance

Async loading lets resources download without blocking the page — async/defer scripts, lazy images, dynamic imports. Critical for fast LCP + low TBT.

What is asynchronous loading?

Asynchronous loading is the practice of fetching resources (scripts, stylesheets, images, code modules) without blocking the page's parsing, rendering, or main thread. Done right, async loading can shave seconds off page load — done wrong, it causes layout shifts, race conditions, and worse UX than synchronous loading.

The browser's parser is single-threaded by default: a synchronous <script> tag halts HTML parsing until the script downloads + executes. Async loading techniques let parsing continue in parallel.

Async loading techniques

TechniqueWhat it doesBest for
<script async>Download in parallel; execute when ready (out of order)Independent third-party scripts
<script defer>Download in parallel; execute after parsing in document orderApp scripts that need DOM ready
<script type="module">Defer by default; ESM importsModern app code
<img loading="lazy">Defer image load until near viewportBelow-the-fold images
Dynamic import()Load JS module on demandCode splitting, route-based loading
requestIdleCallbackRun code during browser idle timeNon-critical work (analytics, prefetch)
Web WorkersBackground-thread JS executionHeavy compute without UI freeze
fetch() + PromisesAsync HTTP requestsData loading after initial render

async vs defer: the critical distinction

<!-- Sync (default): blocks parsing -->
<script src="app.js"></script>

<!-- async: download in parallel, execute IMMEDIATELY when ready -->
<script async src="analytics.js"></script>

<!-- defer: download in parallel, execute AFTER parsing in order -->
<script defer src="app.js"></script>
Aspectasyncdefer
Order of executionWhichever loads firstDocument order
Executes whenAs soon as downloadedAfter HTML parsed
Blocks parser?NoNo
DOM ready?Maybe notYes (always)
Best forIndependent scripts (analytics, ads)App code that needs DOM

Rule of thumb: Use defer for your code, async for third-party scripts that don't depend on anything.

Image lazy-loading

<!-- Native lazy-load: defer until near viewport -->
<img src="hero.jpg" loading="eager" alt="Hero" width="1200" height="600">
<img src="footer-banner.jpg" loading="lazy" alt="Banner" width="800" height="200">

<!-- iframes too -->
<iframe src="https://youtube.com/..." loading="lazy"></iframe>

Native lazy-loading is supported in all modern browsers. loading="eager" is the default; loading="lazy" defers.

Dynamic imports for code splitting

// Static import: bundled into main JS
import { heavy } from './heavy-module';

// Dynamic import: loaded on demand
button.addEventListener('click', async () => {
  const { openModal } = await import('./modal');
  openModal();
});

// Route-based: load each route only when navigated to
const Settings = lazy(() => import('./Settings'));

Async data loading patterns

// Fetch + render — old style
fetch('/api/users')
  .then(r => r.json())
  .then(users => render(users));

// Modern: async/await
async function loadUsers() {
  const res = await fetch('/api/users');
  const users = await res.json();
  render(users);
}

// Concurrent fetches
const [users, posts] = await Promise.all([
  fetch('/api/users').then(r => r.json()),
  fetch('/api/posts').then(r => r.json())
]);

Async loading best practices

  • Use defer for app scripts. Don't block parsing; run after DOM ready.
  • Use async for analytics + ads. Independent scripts; don't care about order.
  • Lazy-load below-the-fold images. loading="lazy".
  • Eager-load LCP image. fetchpriority="high" + preload.
  • Code-split routes. Dynamic imports per route.
  • Use Promise.all for concurrent fetches. Don't wait sequentially.
  • Show loading states. Skeletons, spinners during async work.
  • Handle errors. Every fetch can fail; user-friendly error UI.
  • Throttle/debounce expensive async ops. Especially in scroll/input handlers.

Common pitfalls

  • async on app code that needs DOM. Script runs before DOM ready; fails or weird behavior.
  • Lazy-load above-the-fold image. Hurts LCP.
  • Sequential awaits when parallel possible. Doubles loading time.
  • Forgetting error handling on async. Unhandled promise rejection in console.
  • No loading state. Page looks broken during async fetch.
  • Race conditions. Two async ops update same state; whichever finishes last wins (often wrong).
  • Memory leaks from uncancelled async. Component unmounts but async still resolves; updates dead state.
  • Blocking await in critical path. Awaiting non-essential data delays render.

FAQ: asynchronous loading

async vs defer: which to use?

defer for your code (executes after DOM ready, in order). async for independent third-party (analytics, ads).

Does lazy-loading work on all browsers?

Native loading="lazy": ~95%+ of browsers (Safari 15.4+, Chrome 77+, Firefox 75+). For older browsers, IntersectionObserver polyfill.

How does dynamic import affect bundle size?

Dramatically — code is split into separate chunks loaded on-demand. Initial bundle drops; subsequent navigation slightly slower (network fetch).

Should I lazy-load all images?

No — lazy-load only below-the-fold. Above-the-fold (especially LCP) should be eager + high priority.

What's a race condition in async code?

Two async operations finish in unexpected order. Common: user types in search box, two requests fire, slower one returns last + overwrites correct results.

How do I cancel an async fetch?

AbortController: const ctrl = new AbortController(); fetch(url, { signal: ctrl.signal }); ctrl.abort();

What's the difference between Promise and async/await?

Same thing. async/await is syntactic sugar over Promises — easier to read, especially with sequences.

Test async-loading impact with LoadFocus

LoadFocus runs Lighthouse audits from 25+ regions, measuring LCP/INP/TBT — directly affected by async loading correctness. Sign up free at loadfocus.com/signup.

How fast is your website?

Elevate its speed and SEO seamlessly with our Free Speed Test.

Free Website Speed Test

Analyze your website's load speed and improve its performance with our free page speed checker.

×