← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Web Locks API — Coordinating Across Tabs

JavaScript HTML5 Intermediate
debt(d7/e3/b3/t5)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). No detection tools are listed in detection_hints.tools. The common mistakes (not awaiting the outer call, generic lock names, missing timeout) are behavioral concurrency bugs that won't surface in static analysis or default linting — they only manifest at runtime when two tabs actually compete, making them invisible until tested under real concurrent conditions.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is a single wrapping pattern — await navigator.locks.request('unique-lock-name', async () => { ... }) — but applying it correctly requires reviewing all call sites for the awaiting mistake and renaming generic lock names. That's a small but non-trivial refactor within affected components, slightly more than a one-line patch.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Web Locks apply within an origin's concurrency-sensitive code paths. The choice imposes a naming discipline (unique lock names per feature) and a fallback concern for older Safari, but these costs are contained to the modules that actually do cross-tab coordination. The rest of the codebase is unaffected.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception field identifies the canonical trap: developers coming from localStorage-flag polling assume Web Locks are just a nicer version of that pattern, missing the automatic crash-release guarantee. Additionally, not awaiting the outer request() call is a documented gotcha that causes subtle concurrency bugs. These are real traps most developers encounter, but they're documented and learnable.

About DEBT scoring →

Also Known As

Web Locks API navigator.locks browser mutex tab coordination

TL;DR

The Web Locks API lets JavaScript in the same origin coordinate exclusive or shared access to a named resource across multiple tabs, workers, or iframes — a browser-native mutex.

Explanation

navigator.locks.request(name, callback) acquires a lock with the given name and calls the callback when the lock is held. If another context holds the same lock, the request queues until the lock is released. When the callback's returned Promise resolves, the lock is released. Mode 'exclusive' (default) allows only one holder; mode 'shared' allows multiple concurrent readers. Locks are automatically released if the tab crashes or is closed. Common use cases: preventing duplicate form submissions across tabs, coordinating IndexedDB migrations, ensuring only one tab performs a background sync, and preventing race conditions in shared-worker scenarios.

Common Misconception

The Web Locks API replaces localStorage-based tab locking. localStorage locking (setting a flag and polling) is unreliable — tabs can crash without clearing the flag. Web Locks are held by the browser and automatically released on crash or close, making them genuinely reliable.

Why It Matters

Multi-tab web apps face real concurrency problems: two tabs submitting the same form, two tabs running the same background sync, IndexedDB schema migrations conflicting. The Web Locks API provides a native, crash-safe mutex without needing a service worker or SharedArrayBuffer.

Common Mistakes

  • Not awaiting the navigator.locks.request() call — the lock is released when the callback Promise resolves; if you don't await the outer call, the surrounding code continues before the lock work finishes.
  • Using the same lock name for unrelated operations — lock names are global within an origin; a generic name like 'sync' will block unrelated features.
  • Not handling lock acquisition timeout — by default, lock requests queue indefinitely; use { signal: AbortSignal.timeout(5000) } to abort if the lock isn't available within 5 seconds.
  • Expecting Web Locks to work in Safari before 15.4 — check caniuse.com; for older browsers fall back to a BroadcastChannel-based coordination approach.

Code Examples

✗ Vulnerable
// ❌ Race condition — multiple tabs submit the same form simultaneously
async function submitOrder(data) {
    // Tab A and Tab B both call this at the same time
    const response = await fetch('/api/orders', {
        method: 'POST', body: JSON.stringify(data)
    });
    // Two orders created — customer charged twice
}
✓ Fixed
// ✅ Web Locks — only one tab processes at a time
async function submitOrder(data) {
    await navigator.locks.request('order-submit', async () => {
        // Only one tab holds this lock at a time
        const response = await fetch('/api/orders', {
            method: 'POST', body: JSON.stringify(data)
        });
        return response.json();
    });
}

// Shared lock — multiple readers, exclusive writer
async function readCache() {
    return navigator.locks.request(
        'cache-lock',
        { mode: 'shared' }, // Multiple tabs can read simultaneously
        async () => getFromCache()
    );
}

// Non-blocking lock query
const state = await navigator.locks.query();
console.log('Held locks:', state.held);
console.log('Pending:', state.pending);

Added 23 Mar 2026
Edited 5 Apr 2026
Views 103
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T
No pings yet today
No pings yesterday
PetalBot 11 Amazonbot 10 SEMrush 7 ChatGPT 6 Perplexity 4 Bing 4 Google 3 Majestic 2 Scrapy 2 Applebot 2 Meta AI 1 Twitter/X 1
crawler 50 crawler_json 3
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
JavaScript javascript The programming language of the browser — it reads and modifies the page (the DOM), reacts to user events, and fetches data without reloading.

JavaScript is the only language browsers execute, so every interactive behaviour on the web goes through it. Its two defining traits — single-threaded event loop and loose typing (== coercion) — explain the majority of both its bugs and its design patterns.

💡 Default to const, use === always, and reach for let only when a value genuinely reassigns.

Ask Codex about JavaScript →
DEV INTEL Tools & Severity
⚙ Fix effort: Medium
⚡ Quick Fix
Wrap any operation that must run in only one tab with: await navigator.locks.request('unique-lock-name', async () => { await doExclusiveWork(); });
📦 Applies To
javascript HTML5 web cli


✓ schema.org compliant