Capabilities · API
Web Locks API: exclusive and shared named locks
Published Updated
In one line: The Web Locks API’s navigator.locks.request() method asynchronously
requests a named lock, runs a callback while holding it, and releases the lock once the
callback settles, letting scripts in different tabs or workers coordinate access to a
shared resource.
Requesting a lock
Section titled “Requesting a lock”await navigator.locks.request('my_resource', async (lock) => { // Only one holder of an exclusive lock named 'my_resource' runs this at a time. await doWork();});Exclusive vs. shared locks
Section titled “Exclusive vs. shared locks”Per the specification, requesting a lock defaults to mode: 'exclusive': while an
exclusive lock is held, no other lock request with the same name is granted. A shared
lock behaves differently — multiple shared requests for the same name can be granted
concurrently, while an exclusive request for that name still waits:
await navigator.locks.request('my_resource', { mode: 'shared' }, async () => { await readSharedData();});An exclusive lock only prevents another cooperating caller from acquiring the same named
lock through this API — it does not stop code that bypasses navigator.locks from reading
or writing the underlying resource directly.
Scope: agents sharing a storage bucket
Section titled “Scope: agents sharing a storage bucket”MDN describes locks as coordinating tabs and workers of the same origin. The specification is more precise: cooperative coordination happens within the set of agents that share a storage bucket, which may span multiple agent clusters. Contexts that end up in different storage partitions or buckets are therefore not guaranteed to share a lock manager, even on the same origin.
Feature detection and fallback
Section titled “Feature detection and fallback”async function withResourceLock(name, fn) { if (!('locks' in navigator)) { // No Web Locks support: run the callback directly without requesting a lock. return fn(); } return navigator.locks.request(name, fn);}Practical checklist
Section titled “Practical checklist”- Per MDN, the API is restricted to secure contexts (HTTPS), and the specification
marks it
SecureContext. - The specification lets applications choose their lock naming scheme, but names
beginning with U+002D HYPHEN-MINUS (
-) are reserved; requesting one causes an exception. - Holding an exclusive lock only blocks other callers that go through
navigator.locks.request()— it cannot stop code that touches the resource without requesting the lock. - Use the
ifAvailableoption to fail fast instead of queuing, and anAbortSignalto time out a request that waits too long.
Where to go next
Section titled “Where to go next”Specifications
| Specification | Status |
|---|---|
| Web Locks API | W3C draft |
- Legend
- Yes
- Partial
- Flag
- No
- Unknown
| Browser / Platform | Support | Versions | Confidence | Source | Notes |
|---|---|---|---|---|---|
| Chrome (Desktop) | Yes | 69 | high | source | — |
| Chrome (Android) | Yes | 69 | high | source | 1 |
| Edge (Desktop) | Yes | 79 | high | source | 2 |
| Firefox (Desktop) | Yes | 96 | high | source | — |
| Firefox (Android) | Yes | 96 | high | source | 3 |
| Safari (macOS) | Yes | 15.4 | high | source | — |
| Safari (iOS) | Yes | 15.4 | high | source | 4 |
| Samsung Internet | Yes | 10.0 | high | source | 5 |
| WebView (Android) | Yes | 69 | high | source | 6 |
- Derived by browser-compat-data mirroring from Chrome.
- Derived by browser-compat-data mirroring from Chrome.
- Derived by browser-compat-data mirroring from Firefox.
- Derived by browser-compat-data mirroring from Safari.
- Derived by browser-compat-data mirroring from Chrome Android.
- Derived by browser-compat-data mirroring from Chrome Android.