JavaScript Navigator locks Property

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Baseline
Secure context

What You’ll Learn

navigator.locks is the entry point for the Web Locks API. Learn the LockManager, request() / query(), coordinating tabs, secure context rules, five examples, and try-it labs.

01

Kind

Read-only property

02

Returns

LockManager

03

Baseline

Widely available

04

Context

Secure (HTTPS)

05

Request

locks.request()

06

Inspect

locks.query()

Introduction

Open the same web app in two tabs and both might try to sync data at once. That can corrupt IndexedDB writes or waste bandwidth. Web Locks let those tabs take turns on a named resource.

navigator.locks returns a LockManager. You call request(name, callback) to acquire a lock, do async work inside the callback, and the lock is released automatically when the callback finishes.

💡
Origin-scoped

Locks are per origin. A tab on https://example.com does not share locks with https://other.com. Workers on the same origin can use them too.

Understanding the locks Property

Think of navigator.locks as a lock desk for your origin: request a named lock, hold it while you work, then let the next waiter in.

  • LockManager — object returned by navigator.locks.
  • request(name, cb) — run cb while holding the lock.
  • Auto-release — when the callback (and its awaits) complete.
  • query() — snapshot of held and pending locks.
  • Modes — default exclusive; optional shared.
  • Secure context — HTTPS / localhost required.

📝 Syntax

General form of the property:

JavaScript
navigator.locks

Value

  • A LockManager object with request() and query().

Common patterns

JavaScript
// MDN-style request (lock released when callback finishes):
navigator.locks.request("my_resource", async (lock) => {
  // The lock has been acquired.
  await doSomething();
  // Now the lock will be released.
});

// Await the whole request (resolves after release):
await navigator.locks.request("my_resource", async (lock) => {
  await doSomethingWithLock();
});

// Inspect held / pending locks:
const state = await navigator.locks.query();

⚡ Quick Reference

GoalCode
Get LockManagernavigator.locks
Detect APIBoolean(navigator.locks)
Request exclusive locknavigator.locks.request(name, async (lock) => { … })
Only if free nowrequest(name, { ifAvailable: true }, cb)
Query stateawait navigator.locks.query()
Secure page?window.isSecureContext
Status (MDN)Baseline Widely available

🔍 At a Glance

Four facts to remember about navigator.locks.

Returns
LockManager

API entry

Baseline
widely

Since ~Mar 2022

HTTPS
required

Secure context

Scope
per origin

Tabs + workers

📋 Web Locks vs local flags

Web Locks (navigator.locks)A boolean in one tab
Cross-tab?Yes (same origin)No
Workers?YesOnly if you invent messaging
ReleaseAutomatic when callback endsEasy to forget / leak
QueueBuilt-in waitersYou build it yourself
Best forSync leaders, shared resourcesIn-page UI toggles

Examples Gallery

Examples follow MDN Web Locks / navigator.locks patterns. Prefer Try It Yourself on HTTPS. Open two tabs to see exclusive locking in action.

📚 Getting Started

Detect the API and confirm a secure context.

Example 1 — Feature Detection

Check whether the Web Locks entry point exists.

JavaScript
const supported = Boolean(navigator.locks);
console.log(supported ? "Web Locks available" : "Web Locks missing");
Try It Yourself

How It Works

On modern HTTPS browsers this is usually available. Still feature-detect for older engines.

Example 2 — Secure Context Check

Web Locks require HTTPS / localhost.

JavaScript
console.log("secure: " + window.isSecureContext);
console.log("locks: " + Boolean(navigator.locks));

if (!window.isSecureContext) {
  console.log("Serve over HTTPS to use navigator.locks");
} else if (!navigator.locks) {
  console.log("Secure, but Web Locks not exposed");
} else {
  console.log("Ready to call request / query");
}
Try It Yourself

How It Works

Localhost counts as a secure context for development.

📈 Practical Patterns

Request a lock, query state, and try ifAvailable.

Example 3 — Request a Named Lock

MDN’s core pattern: acquire, work, auto-release.

JavaScript
async function runWithLock() {
  if (!navigator.locks) {
    return "Web Locks not supported.";
  }
  return navigator.locks.request("demo_resource", async (lock) => {
    // The lock has been acquired.
    return "held: " + lock.name + " (mode: " + lock.mode + ")";
  });
}

runWithLock().then(console.log);
Try It Yourself

How It Works

The promise from request() resolves after the lock is released — often with the callback’s return value.

Example 4 — Query Held and Pending Locks

Take a snapshot with query() for debugging.

JavaScript
async function snapshot() {
  if (!navigator.locks) {
    return "Web Locks not supported.";
  }
  const state = await navigator.locks.query();
  return JSON.stringify({
    held: state.held.length,
    pending: state.pending.length
  });
}

snapshot().then(console.log);
Try It Yourself

How It Works

The result is a moment-in-time snapshot — useful when a lock seems stuck.

Example 5 — ifAvailable (No Waiting)

Try to become the “leader” only if the lock is free right now.

JavaScript
async function tryBecomeLeader() {
  if (!navigator.locks) {
    return { ok: false, reason: "unsupported" };
  }
  return navigator.locks.request(
    "sync_leader",
    { ifAvailable: true },
    async (lock) => {
      if (!lock) {
        return { ok: false, reason: "busy" };
      }
      return { ok: true, name: lock.name };
    }
  );
}

tryBecomeLeader().then((r) => console.log(JSON.stringify(r)));
Try It Yourself

How It Works

With ifAvailable: true, the callback may receive null instead of waiting in the queue.

🚀 Common Use Cases

  • Sync leader election — only one tab syncs network ↔ IndexedDB.
  • Shared resource guards — serialize access to a named critical section.
  • Multi-tab editors — prevent conflicting writes to the same store.
  • Worker coordination — same API available in Web Workers.
  • Diagnosticsquery() to see who holds what.

🧠 How navigator.locks Works

1

Request a named lock

navigator.locks.request("my_resource", callback).

Request
2

Callback runs while held

Do async work; other tabs wait for the same name.

Hold
3

Callback finishes

The lock is released automatically.

Release
4

Next waiter is granted

Queued requests proceed in order for that lock name.

📝 Notes

  • Baseline Widely available (MDN, since about March 2022).
  • Not Deprecated, Experimental, or Non-standard — no status banner required.
  • Secure context required (HTTPS / localhost).
  • Also available as WorkerNavigator.locks in workers.
  • Related: login, languages, JavaScript hub.

Universal Browser Support

navigator.locks (Web Locks API) is Baseline Widely available across modern browsers (MDN: since about March 2022). Use it over HTTPS to coordinate tabs and workers on the same origin.

Baseline · Widely available

Navigator.locks

Request named locks, run work in the callback, query held/pending state, and release automatically when done.

Universal Widely available
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
locks Excellent

Bottom line: Use navigator.locks.request for cross-tab coordination. Prefer ifAvailable for non-blocking leader checks.

Conclusion

navigator.locks is the Web Locks entry point. Feature-detect it in a secure context, call request() with a named resource, keep critical work inside the callback, and use query() when you need a status snapshot.

Continue with login, languages, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Use clear lock names (sync_leader, db_write)
  • Keep the critical section inside the callback
  • Prefer async callbacks so release waits for awaits
  • Use ifAvailable when waiting is undesirable
  • Serve over HTTPS / localhost

❌ Don’t

  • Nest locks carelessly (deadlock risk)
  • Hold locks longer than needed
  • Assume locks work across different origins
  • Forget that release is tied to callback completion
  • Use steal unless you understand the disruption

Key Takeaways

Knowledge Unlocked

Five things to remember about locks

Baseline LockManager for coordinating tabs and workers.

5
Core concepts
🔓 02

Request

Named lock

Hold
🔄 03

Release

Auto on finish

Callback
🔍 04

Query

Held / pending

Debug
05

Status

Baseline

HTTPS

❓ Frequently Asked Questions

It is a read-only Navigator property that returns a LockManager — the entry point for the Web Locks API so tabs and workers on the same origin can request and query named locks.
No. MDN marks it Baseline Widely available (since about March 2022). It is not Deprecated, Experimental, or Non-standard.
Yes. It is available only in secure contexts (HTTPS or localhost) in supporting browsers.
Call navigator.locks.request(name, async (lock) => { … }). The callback runs while the lock is held; when the callback finishes (including awaited work), the lock is released automatically.
navigator.locks.query() returns a Promise that resolves with a snapshot of held and pending locks for the origin — useful for debugging why a lock could not be acquired.
To coordinate work across multiple tabs or workers — for example so only one tab syncs IndexedDB to the network at a time (leader election).
Did you know?

MDN’s classic use case is leader election: every tab requests "my_net_db_sync", but only one holds the exclusive lock and performs the sync while the others wait or skip with ifAvailable.

Explore login Next

Learn the Login Status API used by FedCM identity providers.

login →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful