How to Inspect and Debug Web Locks in Google Chrome DevTools

Modern complex web applications frequently execute across multiple simultaneous browser contexts: users open multiple browser tabs of the same application, background Service Workers execute sync tasks, and nested iframes communicate with parent windows. When these separate contexts access shared client storage (such as IndexedDB databases, Cache API stores, or localStorage), simultaneous writes can easily cause race conditions and state corruption.

The W3C Web Locks API (navigator.locks) allows web applications to coordinate asynchronous execution by acquiring mutually exclusive or shared locks across origins. To help developers inspect lock ownership and troubleshoot deadlocks, Google Chrome DevTools includes a dedicated Web Locks inspection tool inside the Application panel.

Understanding the Web Locks API

The Web Locks API coordinates resource access using a simple request pattern:

// Request an exclusive lock on a shared resource
navigator.locks.request('order_processing_lock', async (lock) => {
  // Critical section: only one tab/worker can execute this block at a time
  await syncOrderDatabase();
  console.log('Order processed cleanly.');
});

Locks are held until the passed asynchronous callback resolves. If a second tab requests the same lock while it is occupied, the second request is queued until the first tab releases it.

Accessing the Web Locks Tool in Chrome DevTools

To inspect active locks and queued requests:

  1. Open Google Chrome and press F12 (or Ctrl + Shift + I on Windows/Linux, Command + Option + I on macOS) to open DevTools.
  2. Click the Application tab along the top toolbar.
  3. In the left sidebar, expand the Storage category.
  4. Click on Web Locks.

Inspecting Active and Pending Locks

The Web Locks panel displays a structured real-time table of all locks currently managed by Chromium’s browser engine for the active origin:

  • Resource / Name: The string identifier assigned to the lock (e.g., order_processing_lock).
  • Mode: Indicates lock concurrency:
    • exclusive: Only one execution context can hold the lock. All other requests must wait.
    • shared: Multiple readers can hold the lock simultaneously, but exclusive writer requests are queued.
  • Status: Displays whether the lock is currently Held (actively executing) or Pending (queued waiting for availability).
  • Client ID: A unique GUID identifying the exact execution context (tab window ID, iframe, or Service Worker) holding or requesting the lock.

Diagnosing Multi-Tab Deadlocks and Starvation

The Web Locks tool is invaluable for detecting application deadlocks:

  1. Open two separate browser tabs navigating to your application.
  2. Trigger a long-running transaction in Tab 1. In DevTools, observe that the lock reports status Held.
  3. Trigger the transaction in Tab 2. Observe that Tab 2 appears in the table with status Pending.
  4. If an unhandled exception or hung Promise occurs in Tab 1 without resolving, the lock remains perpetually Held, starving Tab 2.

Best Practices for Implementing Resilient Web Locks

To prevent deadlocks and maintain smooth multi-tab experiences:

  • Use Non-Blocking Opportunistic Locks: Use the ifAvailable: true option when a background task can simply be skipped if another tab is already handling it:
    navigator.locks.request('poll_server', { ifAvailable: true }, async (lock) => {
      if (!lock) return; // Another tab is already polling
      await pollUpdates();
    });
  • Implement AbortSignals: Pass an AbortSignal with a timeout to cancel lock requests that remain queued for too long, preventing user interfaces from hanging indefinitely.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.