Distributed Locking in .NET: Redis vs SQL Server vs Azure Blob β Enterprise Decision Guide

Distributed locking is a foundational pattern for building reliable concurrent systems in .NET. When multiple processes or services need to coordinate access to a shared resource β whether it's a cache key, a file, or a database row β the wrong choice can lead to deadlocks, duplicate processing, or silent data corruption. Redis, SQL Server, and Azure Blob Storage each offer locking mechanisms with different trade-offs in performance, reliability, and operational complexity.
This guide gives you the decision framework, performance benchmarks, and failure mode analysis to choose the right distributed lock strategy for your enterprise system. No academic theory hereβjust production-grade comparisons.
π Want implementation-ready .NET source code you can drop straight into your project? Join Coding Droplets on Patreon for exclusive tutorials, premium code samples, and early access to new content. π Join us on Patreon
When Distributed Locking Actually Matters
Distributed locking is a solution to a very specific problem: ensuring that only one process across multiple machines can perform an action at a time. The need arises frequently in microservices, background job systems, and high-traffic APIs. But the overhead of a distributed lock is realβadd latency, create failure points, and introduce operational complexity.
Use distributed locking when you have:
Exclusive access to a shared resource that cannot tolerate concurrent mutation (e.g., inventory decrement, account balance adjustment)
Long-running operations that must not be duplicated (e.g., scheduled report generation, batch processing)
Resource starvation protection (e.g., rate limiting counters, semaphore for API quota)
Cross-process coordination where the processes do not share memory and may run on different servers
Avoid distributed locking when:
Idempotency can solve the problem β design operations to be safely repeatable instead of locking
Database row-level locks suffice β your database already provides ACID guarantees inside a transaction
Message queue order guarantees removal β use a single consumer instead of locking
The operation is fast β the lock overhead may exceed the work itself
Redis (Redlock Algorithm)
Redis is the most popular choice for distributed locks in the .NET ecosystem due to its speed, simplicity, and built-in atomic operations.
How It Works
The canonical implementation uses the Redlock algorithm: acquire the lock on a majority of N independent Redis nodes (typically 5), with a short TTL. The lock is considered acquired if a majority grants it. This prevents split-brain scenarios where a network partition causes two processes to both think they hold the lock.
In practice, most teams use the RedLock.net library which handles the multi-node consensus logic.
Pros
Sub-millisecond latency β in-memory, single-digit milliseconds round-trip
High throughput β can handle thousands of lock/unlock operations per second
TTL enforcement β automatic expiration prevents permanent deadlocks if a client crashes
Well-documented pattern β Redlock is widely understood and battle-tested
Cons
Clock drift sensitivity β TTL relies on synchronized clocks; skewed clocks can cause premature expiration or lock leaks
Operational overhead β requires running and monitoring multiple Redis nodes (minimum 3, recommended 5)
Not a silver bullet β Redlock makes strong assumptions about network behavior; Jepsen-style analyses have shown edge-case failures under extreme partition scenarios
Extra dependency β you need Redis for locking, not just data caching
SQL Server (Application Locks)
SQL Server provides sp_getapplock and sp_releaseapplock stored procedures for user-defined locks at the database level. These are lightweight mutexes that live inside the database transaction.
How It Works
An application lock is identified by a resource name (string) and a lock mode (Exclusive, Shared, Update). It is acquired within a transaction scope and automatically released when the transaction ends (commit or rollback). This ties the lock lifetime to the database transaction, simplifying cleanup.
EXEC sp_getapplock @Resource = 'MyLock', @LockMode = 'Exclusive', @LockTimeout = 5000;
Pros
Zero additional infrastructure β you already have a database
Transaction-scoped lifetime β no manual release required if you roll back
Strong consistency β lock state is durable and ACID-compliant
Fine-grained timeout control β specify milliseconds to wait
Cons
Higher latency β round-trip to database (typically 1β5 ms, depending on network and load)
Limited throughput β each lock uses database resources; high contention hurts database performance
Single point of failure β your database is now a lock service; if it goes down, so does your coordination
Not distributed across regions β database latency across geographic regions is too high for locking
Azure Blob Storage (Lease Blob)
Azure Blob Storage offers a lease mechanism that provides exclusive write access to a blob for a fixed period. The lease is renewable and breakable.
How It Works
Call AcquireLease on a blob (or container) to obtain a lease ID. The lease lasts 15β60 seconds and can be renewed. While a lease is held, other clients can only read the blob β writes require the lease ID. Releasing or breaking the lease frees the lock.
Pros
Geo-replicated durability β the lock state survives regional failover (if using RA-GRS)
Simple API β one REST call to acquire, one to release
Infrastructure-free β no Redis cluster, no extra database load; uses existing Blob Storage account
Renewable β background process can renew the lease while work continues
Cons
High latency β Azure Storage round-trip is typically 20β50 ms, much slower than Redis or SQL
Coarse resource unit β locks a blob or container, not arbitrary resources
Lease duration limitations β max 60 seconds per lease; you must implement renewal logic for long operations
Not suitable for high-frequency locks β too slow for tight coordination loops
Side-by-Side Comparison
| Aspect | Redis (Redlock) | SQL Server AppLock | Azure Blob Lease |
|---|---|---|---|
| Typical latency | 1β3 ms | 1β5 ms | 20β50 ms |
| Throughput | Very high | Medium | Low |
| TTL enforcement | Automatic (ms) | Manual (transaction scope) | Automatic (15β60s lease) |
| Infrastructure | Redis cluster (3β5 nodes) | Existing SQL Server | Existing Blob Storage |
| Consistency model | Eventual (clock-based TTL) | Strong (transactional) | Eventual (storage-replicated) |
| Geographic suitability | Single region / low latency | Single region | Multi-region (lease is global) |
| Failure cleanup | TTL expiration | Transaction rollback | Lease expiration |
| Best for | High-frequency locks, microservices in one region | Database-centric coordination, transactional jobs | Low-frequency, cross-region coordination |
Decision Matrix: Which One to Choose?
| Your scenario | Recommended choice | Why |
|---|---|---|
| High-frequency locks (>10/sec), microservices in one region, already have Redis | Redis | Speed and throughput win; use Redlock for safety |
| Locks tightly coupled to database transactions, moderate frequency | SQL AppLock | No new infra; lifetime tied to transaction |
| Low-frequency coordination (<1/sec), cross-region, already on Azure | Blob Lease | Geo-replicated durability sufficient for occasional locks |
| Simple "only one instance" startup guard, no infra changes allowed | SQL AppLock (quickest) or Blob Lease (if on Azure) | Choose whatever you already have |
| You already use Redis for caching and it's in the same VNet | Redis | Leverage existing deployment and network proximity |
| Need guaranteed cleanup even if process dies | Redis TTL or Blob Lease | Both auto-expire; SQL applock needs explicit release or transaction rollback |
Implementation Gotchas
Redis: Always set a TTL. Use the RedLock.net library instead of rolling your own. Be aware that network blips can cause LockException β wrap lock acquisition in retry logic with backoff. Monitor lock acquisition latency; a sudden increase indicates Redis node issues.
SQL: Do not hold locks across long operations outside a transaction. If your work takes 30 seconds, keep the transaction short and release the lock, or risk blocking others. sp_getapplock returns a status; check it. Avoid using the same lock name for different purposes to prevent deadlock.
Blob: Lease renewal must happen before the lease expires β schedule a background timer at 80% of lease duration. If renewal fails, treat it as a lost lock and abort the operation. Blob lease errors often come back as 409 Conflict or 412 Precondition Failed.
FAQ
What happens if a Redis node goes down while holding a lock? If you're using Redlock with 5 nodes and 3 grant the lock, losing 2 nodes doesn't release the lock. The TTL ensures the lock eventually expires even if the remaining nodes lose the lease data. Set the TTL generously enough to cover your operation, but not too long (to avoid long wait times after crash).
Can I use SQL Server Application Lock with Entity Framework? You can execute raw SQL via DbContext.Database.ExecuteSqlRaw or use an IDbConnection directly. EF doesn't have built-in abstraction for app locks, but it's straightforward to call sp_getapplock and sp_releaseapplock when needed.
Is Azure Blob Lease safe for critical financial operations? Probably not. The latency (20β50 ms) may be acceptable, but the eventual consistency model of Blob Storage means there is a small window where two clients might both think they hold the lease. For high-value operations, use Redis or SQL with stronger guarantees.
How long should I set my Redis lock TTL? Long enough to cover your operation plus a safety margin (e.g., if the work takes 2 seconds, set TTL to 10 seconds). Short TTLs risk losing the lock before work completes; long TTLs risk blocking others unnecessarily if the process crashes.
What about etcd or Consul? Those are excellent choices for service discovery and configuration, but they add operational complexity. If you already have them, their lock implementations are robust. The three options above cover most .NET enterprise scenarios without introducing a new dependency.
Conclusion
Redis wins for speed and throughput when you already have a Redis cluster. SQL Server wins for simplicity when locks are tightly coupled to database operations. Azure Blob Lease wins for occasional cross-region coordination without new infra.
Pick based on your existing cloud footprint and latency requirements β not on academic purity.
β Found this article helpful? Buy us a coffee β it helps us keep producing free, high-quality .NET content every week.






