How to acquire a lock by a key
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
In software, "acquiring a lock by a key" usually means serializing work per logical identifier. For example, two threads processing the same customer ID should not run at the same time, but work for different customer IDs should still proceed concurrently.
That pattern is often called keyed locking or per-key locking. It is useful for caches, account updates, job deduplication, and any workflow where contention should be isolated to one specific resource instead of a single global mutex.
Why a Global Lock Is Often Too Coarse
A single global lock is easy to write, but it kills concurrency:
This prevents races, but it also blocks unrelated accounts from running in parallel. If thread A is working on "acct-1", thread B handling "acct-2" is forced to wait even though there is no shared business conflict.
Keyed locking narrows the scope so only identical keys contend.
A Simple Keyed Lock in Python
One straightforward implementation uses:
- a dictionary from keys to locks
- a separate guard lock to protect that dictionary
With this design, calls for the same account_id serialize, while different account IDs can proceed independently.
A Context Manager Version
Returning a lock object works, but a context manager is easier to use correctly:
This reduces the chance of forgetting to release the lock in an error path.
Important Design Detail: Cleaning Up Unused Locks
The simple dictionary approach can leak entries if you keep creating new keys forever. If your key space is unbounded, the map will grow without limit.
A production implementation often adds:
- a reference count for active holders and waiters
- removal of unused lock objects when the count drops to zero
- time-based cleanup if keys are extremely dynamic
That bookkeeping is the hard part of keyed locking. The basic idea is easy; making it scale safely takes more care.
When to Use Semaphore Instead of Lock
Sometimes you want a per-key concurrency limit larger than one. In that case, use a keyed semaphore instead of a keyed mutex.
That pattern allows up to three concurrent operations for the same key instead of exactly one.
Alternatives in Other Environments
The same concept appears in many ecosystems:
- Java with
ConcurrentHashMap<Key, ReentrantLock> - C# with
ConcurrentDictionary<TKey, SemaphoreSlim> - distributed systems with Redis or database-backed locks
If work may happen on multiple machines, an in-process keyed lock is not enough. Then you need a distributed coordination mechanism keyed by the same logical resource ID.
Common Pitfalls
The biggest pitfall is forgetting to protect the dictionary of locks itself. If multiple threads create per-key locks without a guard, you can accidentally create two different lock objects for the same key and lose mutual exclusion.
Another mistake is never removing old keys. A keyed-lock table with an unbounded key space can become a memory leak over time.
Developers also sometimes use keyed locking when optimistic concurrency or atomic database updates would be simpler. A lock is not always the best fix.
Finally, an in-process keyed lock only protects one process. If multiple application instances can modify the same resource, you need a distributed locking or transaction strategy instead.
Summary
- Keyed locking serializes work per logical resource instead of globally.
- It is useful when identical keys must not overlap, but different keys may run in parallel.
- A dictionary of per-key locks plus a guard lock is the basic implementation pattern.
- Context-manager style APIs reduce release bugs.
- Production implementations need a plan for cleaning up unused keys.
- In multi-process or multi-node systems, use a distributed coordination mechanism instead of an in-memory keyed lock.
Related reading
- How to add basic authentication for Tensorflow serving
- How to add basic authentication header to WebRequest
- How to add manifest permission to an application?
- How to add more devices to AWS root account MFA
- How to add new cluster in ArgoCD use config file of Rancher? - the server has asked for the client to provide credentials
- How to add password to google cloud memorystore
- How to add self signed SSL certificate to jHipster sample app?
- How to add SSL certificate to AWS EC2 with the help of new AWS Certificate Manager service

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.