Skip to main content

Command Palette

Search for a command to run...

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

Updated
β€’9 min read
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.

More from this blog

C

Coding Droplets

119 posts