pwaPeriodic Background Sync Explained

Exploring the periodic background sync JavaScript API, using an example application.

Periodic Background Sync Cover Image

There are a few situations where the internet connection isn't optimal, but you still want to check your phone for news, social media, or other websites. If you want to have a good offline experience, there's usually no way around native mobile apps.

Periodic background syncs are a feature of service workers that brings native features to the web. Like the name already tells us, it allows websites to periodically fetch data in the background without any user interaction, so when users open the site again, they'll be able to read the latest news, even without having an internet connection.

In this article, I'll explain how this works and how you can easily add periodic background syncs to your web application as well.

If you already want to see some code, you can check out the example project I created for this tutorial.*

This feature is part of Project Fugu, a cross-company effort, brought to life by Google, to make the web more powerful. Click here to read more about it.

Watch my PWA online course 📹

You can now watch my course on how to turn your React app into a PWA on Skillshare. Learn what you need to know to get started, and turn your React app into a PWA in just 10 minutes.

Watch it for free with my referral link, which will give you a 14 day trial.

How it works

As you already might know, service workers enable offline capabilities by caching the application code of the website. This means that when the user opens the app, he won't have to wait for the necessary HTML, JavaScript, and CSS to load.

While this greatly improves the page load on subsequent visits, usually, the data that users actually want to see is dynamic. With the current web APIs, there's no way of providing fresh data without an internet connection because we're limited to fetch data while the user is on our website.

The periodic background sync API is here to solve this problem — something that previously only native applications were able to do. Using this API, we're able to provide users with new data even when they don't have an internet connection.

Let's say you want to read the latest news articles on the subway ride to work, but the internet connection is less than optimal. The latest news articles can be fetched periodically in the background, so the user will see relevant data, even without an internet connection.

Periodic background sync !== background sync

Even though these two APIs have similar names, their intention is quite different. Background syncs are usually used for sending data after the user left the page, while the periodic background sync synchronizes data in the background without any user interaction.

Don't always use this

While this API is a nice way to improve the loading times of frequent users, you shouldn't always use it. Consider checking network conditions and the available storage before making a request.

You shouldn't unnecessarily waste precious mobile bandwidth for data the user probably isn't going to need.

Prerequisites

To prevent websites from abusing this, there are a few things your site needs before periodic background syncs are enabled.

In addition to these prerequisites, make sure that your browser is supported.

Progressive Web App

Your site needs to be a Progressive Web App and it needs to be installed to register a periodic background sync.

Internet connection

The sync only happens on internet connections that the device has been connected to before. This is a security measure to prevent doing network requests on untrusted networks.

Site engagement score

Of course, there are concerns about security and extensive data usage when adding an API that allows JavaScript to be executed without any user interaction. That's where Chromium's site engagement score comes into play, which aims to prevent the misuse of this API.

The site engagement score a number between 0 and 100 that is calculated based on how much a user interacts with a website. It also takes into consideration whether the application is installed. You can read more about this on the Chromium website.

For the periodic background sync, this means that the frequency of the possible syncs depends on this score. In the following table, you can see the frequency in hours for a given level of engagement.

Engagement ScorePeriodic Sync
NONENever
MINIMAL36
LOW24
MEDIUM24
HIGH12
MAX12

The MINIMAL bucket represents ~25% of sites, whereas the LOW bucket represents a further ~65% of sites. This means that for most of the sites, they’ll only get the opportunity to sync in the background every 24 or 36 hours, for the service worker execution timeout period, which is 3 minutes in the current implementation. Source

You can check your own engagement scores under chrome://site-engagement/.

Implementation

Enough theory, let's have a look at how you can use this feature in your PWA. For this article, I created a GitHub repository where I tried everything out.

How to register a periodic background sync?

Before we can register a new sync we need to check whether we have the permission to do so. The permission is only granted if the app is installed and we're using a Chromium browser.

const status = await navigator.permissions.query({
  name: 'periodic-background-sync',
});

if (status.state === 'granted') {
  // Continue registering the periodic sync
}

Navigator.permissions returns a Promise that resolves to a Permissions object.

If the permission is granted, we can proceed to register a periodic sync:

if (status.state === 'granted') {
  await registration.periodicSync.register('news', {
    minInterval: 24 * 60 * 60 * 1000, // 1 day in ms
  });
}
'news' is the tag we'll use to identify this registration

Putting all of this together, we'll end up with something like this in our code:

public/index.js
// Check if service workers are supported
if ('serviceWorker' in navigator) {
  const registration = await navigator.serviceWorker.ready;
  // Check if periodicSync is supported
  if ('periodicSync' in registration) {
    // Request permission
    const status = await navigator.permissions.query({      name: 'periodic-background-sync',    });    if (status.state === 'granted') {
      try {
        // Register new sync every 24 hours
        await registration.periodicSync.register('news', {          minInterval: 24 * 60 * 60 * 1000, // 1 day        });        console.log('Periodic background sync registered!');
      } catch(e) {
        console.error(`Periodic background sync failed:\n${e}`);
      }
    }
  }
}
Note that I'm also checking if service workers and period syncs are supported.

In the service worker, we then need to listen to the periodicsync event and update the cache. In this example, fetchAndCacheNews fetches the latest news and adds them to the cache (see the source code here).

public/service-worker.js
self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'news') {
    console.log('Fetching news in the background!');
    event.waitUntil(fetchAndCacheNews());
  }
});

And that's already everything we need to do. In the next section, I'll show you how you can check if your code is working.

Debugging

The features mentioned in this section are available in Chrome v81 or later.

Since periodic background syncs only work when the web application is installed, you need to do so for debugging as well. In Google Chrome you'll find a small + sign on the right side of the URL bar. This only appears if you're not browsing in incognito mode and your PWA is installable (go to DevTools > Lighthouse for debugging issues with this).

Install PWA

You need to install your PWA to debug periodic syncs.

Trigger periodic syncs

Once installed, you hit F12 to open the DevTools. Under Application > Service Worker, you can trigger a periodic sync. Specify the tag name of your sync (in our case news) and press the Periodic Sync button to simulate a sync.

How to trigger a periodic sync

Record activity

In the left menu of the Application tab, you'll find Periodic Background Sync. If you hit the record button, Chrome will record all local periodic sync events for up to 3 days.

Record periodic sync activity

Browser Support

The periodic sync API is currently only supported by Chromium-based browsers. As of writing this article, this is Chrome v80, Edge v80, Android Browser v81, and Chrome for Android v81. You can check out the latest update on caniuse.com.

According to the Chrome Platform Status, Firefox and Safari haven't shown any public signals about this API. This, however, might change if it proves useful to Chromium-based browsers.

Conclusion

While fetching data at a maximal frequency of 12 hours, and only on Chromium browsers, might not seem like a big benefit, it's a step in the right direction, adding more native features to the web. If it proves valuable, other browsers will catch up as well.

Given that there are very few changes necessary to implement this, it might be worth adding it to existing projects anyway and by this, improve the user experience of Chromium users. Just make sure to check for compatibility before using the API.

I'm excited about the future of this technology and other features that hopefully will come to the web as well.

If you've come so far and you're still curious about Progressive Web Apps, you can check out my other articles on PWAs and subscribe to my newsletter to get my latest content by email.

Further reading

Get notified about new tutorials

Join over 1,000 developers who receive React and JavaScript tutorials via email.

No spam. Unsubscribe at any time.