All articles
· 7 min read

The Background Sync API in production

How to use Background Sync and Periodic Background Sync to make offline writes reliable — with browser support caveats and the fallback for Safari.

TI
The InstantPWA team
Product & engineering

Background Sync is the missing piece in every "offline-first" tutorial. Without it, a queued write depends on the user reopening your tab. With it, the browser guarantees the flush the moment the network is back.

One-shot sync

// Page code
const reg = await navigator.serviceWorker.ready;
await reg.sync.register('flush-outbox');
// Service worker
self.addEventListener('sync', (event) => {
  if (event.tag === 'flush-outbox') {
    event.waitUntil(flushOutbox());
  }
});

The browser fires sync when it detects connectivity. Runs even if your tab is closed — the service worker wakes for the event.

Periodic sync

const status = await navigator.permissions.query({ name: 'periodic-background-sync' });
if (status.state === 'granted') {
  await reg.periodicSync.register('refresh-feed', { minInterval: 12 * 60 * 60 * 1000 });
}

Fires roughly every N hours when the app is installed and the device is on Wi-Fi + charging. Great for daily content refresh; useless for real-time.

Browser support

  • Chrome, Edge, Opera: full support.
  • Samsung Internet: one-shot only.
  • Firefox, Safari: neither. Use fallback.

Fallback strategy

if ('sync' in registration) {
  await registration.sync.register('flush-outbox');
} else {
  window.addEventListener('online', flushOutbox);
}

Making it reliable

  • Keep the queue idempotent — sync can fire twice for the same tag.
  • Retry with exponential backoff inside flushOutbox; don’t re-register on failure.
  • Cap queue size to bound worst-case memory.
  • Log a metric on every successful flush — you’ll see the reliability curve.

Ship your install prompt in 60 seconds

InstantPWA is one line of code. Free forever for one widget, no card required.

Get started free