Skip to main content

Command Palette

Search for a command to run...

async vs defer in JavaScript: How Script Loading Really Works

Published
4 min readView as Markdown

How Script Loading Really Works

If you’ve ever added JavaScript to an HTML page, you’ve probably written something like this:

<script src="script.js"></script>

But modern JavaScript gives you two powerful attributes:

  • async

  • defer

They change how scripts load and execute, and using the wrong one can break your page.

In this article, you’ll learn:

  • how browsers load scripts by default

  • what async does

  • what defer does

  • key differences between them

  • when to use each

  • common mistakes

Let’s start with the default behavior.


How Browsers Load JavaScript by Default

When the browser encounters this:

<script src="app.js"></script>

It does three things in order:

  1. Stops parsing HTML

  2. Downloads the JavaScript file

  3. Executes the JavaScript

  4. Resumes parsing HTML

This is called render-blocking.

Problem with Default Behavior

  • Slows down page rendering

  • Bad for performance

  • Especially harmful for large scripts

This is where async and defer help.


What Is async?

The async attribute tells the browser:

“Download this script in parallel, and execute it as soon as it’s ready.”

<script src="async.js" async></script>

How async Works

  1. HTML parsing continues

  2. Script downloads in parallel

  3. HTML parsing pauses when the script finishes downloading

  4. Script executes immediately

Execution time is not predictable.


Example

<script src="analytics.js" async></script>

This is perfect for scripts that:

  • do not depend on DOM

  • do not depend on other scripts


Key Characteristics of async

✔ Downloads in parallel
✔ Executes immediately after download
❌ Execution order not guaranteed
❌ Can interrupt HTML parsing


What Is defer?

The defer attribute tells the browser:

“Download this script in parallel, but execute it after HTML parsing is complete.”

<script src="defer.js" defer></script>

How defer Works

  1. HTML parsing continues

  2. Script downloads in parallel

  3. Script execution waits

  4. Executes after DOM is fully built


Example

<script src="main.js" defer></script>

This is ideal for scripts that:

  • manipulate the DOM

  • depend on HTML elements


Key Characteristics of defer

✔ Downloads in parallel
✔ Executes after HTML parsing
✔ Execution order is preserved
✔ Safe for DOM access


async vs defer: Side-by-Side Comparison

Featureasyncdefer
HTML parsingPauses during executionNever pauses
DownloadParallelParallel
Execution timeAs soon as readyAfter DOM loaded
Order preserved❌ No✔ Yes
DOM safe❌ Not guaranteed✔ Yes
Best forIndependent scriptsApp logic

Execution Order Example

<script src="a.js" async></script>
<script src="b.js" async></script>

Execution order:

  • a.js or b.js (depends on download speed)

<script src="a.js" defer></script>
<script src="b.js" defer></script>

Execution order:

  1. a.js

  2. b.js

Always in order.


When Should You Use async?

Use async when the script:

✔ Is independent
✔ Does not access DOM
✔ Does not depend on other scripts

Common Use Cases

  • Analytics

  • Ads

  • Tracking scripts

<script src="google-analytics.js" async></script>

When Should You Use defer?

Use defer when the script:

✔ Needs DOM access
✔ Depends on other scripts
✔ Is part of your application logic

Common Use Cases

  • Main JS files

  • UI logic

  • Event handlers

<script src="app.js" defer></script>

What About Scripts at the Bottom of <body>?

Old approach:

<script src="app.js"></script>
</body>

Modern approach:

<script src="app.js" defer></script>

✔ Cleaner
✔ Better performance
✔ Recommended


async and defer with Inline Scripts

They do not work with inline scripts.

❌ This does nothing:

<script async>
  console.log("Hello");
</script>

They only work with external scripts.


Common Mistakes

❌ Using async for dependent scripts

<script src="lib.js" async></script>
<script src="app.js" async></script>

app.js may run before lib.js.


❌ Accessing DOM with async

document.getElementById("btn"); // may be null

❌ Mixing async and defer carelessly

Stick to one strategy.


Best Practices

✔ Use defer for most scripts
✔ Use async only when truly independent
✔ Avoid default blocking scripts
✔ Never rely on async execution order
✔ Prefer defer over placing scripts at bottom


Mental Model to Remember

  • Default: Stop → Download → Execute

  • Async: Download → Execute ASAP

  • Defer: Download → Wait → Execute after DOM

More from this blog

Javascript Beginner Articles

23 posts

\n\nBut modern JavaScript gives you two powerful attributes:\n\nasync\n\ndefer\n\n\nThey change how ...","author":{"@type":"Person","name":"Madankumar","url":"https://hashnode.com/@madankumar-sajjanar","image":"https://cdn.hashnode.com/res/hashnode/image/upload/v1755364588231/5ee0c48e-11c0-472b-82d3-1324ef53d0a0.png","sameAs":"https://x.com/MadanSajjanar?t=se8aha2kmvo6N4kqjfQyCw&s=08"},"publisher":{"@type":"Organization","name":"Javascript Beginner Articles","url":"https://javascript-beginner-articles.hashnode.dev"},"datePublished":"2025-12-15T04:22:50.082Z","dateModified":"2025-12-15T04:22:50.082Z","keywords":"JavaScript, js, Beginner Developers, asynchronous JavaScript, Deferred Execution, defer"}