AboutBlogContact
Software ArchitectureJune 28, 2021 2 min read 154Updated: June 22, 2026

Partytown: Offloading Third-Party Scripts to Web Workers (2021)

AunimedaAunimeda
📋 Table of Contents

Partytown: Offloading Third-Party Scripts

It's 2021, and we're still letting Google Tag Manager, Facebook Pixel, and Intercom hijack the main thread. Your TTI (Time to Interactive) is suffering because of scripts you didn't even write. Partytown is the library that finally says "enough" by moving these scripts into a background Web Worker.

The Challenge: Synchronous DOM Access

The reason third-party scripts run on the main thread is that they need synchronous access to the DOM (document.createElement, window.innerWidth, etc.). Web Workers, by design, cannot access the DOM.

Partytown solves this using a clever (and somewhat terrifying) combination of Service Workers and Synchronous XHR.

How the Proxy Works

When a script in the Web Worker tries to access document.title, Partytown intercepts the call with a Proxy.

// Inside the Partytown Web Worker
const docProxy = new Proxy(document, {
  get(target, prop) {
    // We can't just return the value; we need to ask the main thread
    return syncSendMessageToMainThread('get', ['document', prop]);
  }
});

Because the Web Worker needs the result immediately to remain compatible with the script's expectations, it uses a synchronous XHR request. The Service Worker intercepts this request, holds it open, asks the main thread for the value via postMessage, and then responds to the XHR.

Integration Example

You don't just "npm install" Partytown; you configure it to wrap your scripts.

<script>
  /* Partytown Config */
  partytown = {
    forward: ['dataLayer.push'],
  };
</script>

<!-- Instead of type="text/javascript", use type="text/partytown" -->
<script type="text/partytown" src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
<script type="text/partytown">
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'GA_MEASUREMENT_ID');
</script>

Why This is a Big Deal

By moving these scripts off the main thread, you free up the CPU for what actually matters: your application's logic and animations. It's the most aggressive performance optimization technique we've seen since the introduction of async/defer.

Partytown effectively turns the "main thread vs. background thread" battle into a "my code vs. their code" separation.


Aunimeda designs and builds scalable software architectures - from system design to implementation and ongoing engineering.

Contact us to discuss architecture for your project. See also: Custom Software Development, Web Development

Read Also

GraphQL and the N+1 Problem: Solving it with DataLoader (2018)aunimeda
Software Architecture

GraphQL and the N+1 Problem: Solving it with DataLoader (2018)

GraphQL is taking over API design in 2018. But without careful implementation, your resolvers will crush your database with N+1 queries. Facebook's DataLoader is the solution.

GraphQL Schema Design: Thinking in Graphs, Not Endpoints (2015)aunimeda
Software Architecture

GraphQL Schema Design: Thinking in Graphs, Not Endpoints (2015)

Facebook just open-sourced GraphQL. It's time to stop thinking in REST resources and start thinking in edges and nodes. Let's design a Relay-compatible schema.

Backbone.Events: Decoupling Your Spaghetti Code with Pub/Sub (2012)aunimeda
Software Architecture

Backbone.Events: Decoupling Your Spaghetti Code with Pub/Sub (2012)

Large-scale JavaScript applications in 2012 are a mess of jQuery callbacks. Backbone.js offers a way out through its powerful Events module. Let's build a decoupled architecture.

Need IT development for your business?

We build websites, mobile apps and AI solutions. Free consultation.

Get Consultation All articles