levelup.gitconnected.com/designing-fa...
github.com/kriasoft/ws-...
levelup.gitconnected.com/designing-fa...
github.com/kriasoft/ws-...
• Capacity ≫ rate → giant attack window
• Only per-user buckets → aggregate floods melt the DB
• Zero jitter headroom → works on ethernet, fails on 4G
All three come from sizing purely in the lab.
• Capacity ≫ rate → giant attack window
• Only per-user buckets → aggregate floods melt the DB
• Zero jitter headroom → works on ethernet, fails on 4G
All three come from sizing purely in the lab.
- "A distributed lock ≠ a mutex"
- "Locks are leases"
- "Leases expire"
- "Fencing tokens make expiry safe"
🧩 Full explanation + examples (Redis, Postgres, Firestore):
levelup.gitconnected.com/beyond-the-l...
- "A distributed lock ≠ a mutex"
- "Locks are leases"
- "Leases expire"
- "Fencing tokens make expiry safe"
🧩 Full explanation + examples (Redis, Postgres, Firestore):
levelup.gitconnected.com/beyond-the-l...
The system becomes safe by design, not by timing.
The system becomes safe by design, not by timing.
Every lock acquisition returns a fencing token, a monotonically increasing number.
Each write includes the token, and the resource rejects any write with an older token.
✅ Deterministic correctness.
Every lock acquisition returns a fencing token, a monotonically increasing number.
Each write includes the token, and the resource rejects any write with an older token.
✅ Deterministic correctness.
Not even a bug in your code.
It’s a two-party problem:
- "Client thinks it holds the lock"
- "Lock manager knows it expired"
There’s no one to stop the stale client from writing bad data.
Not even a bug in your code.
It’s a two-party problem:
- "Client thinks it holds the lock"
- "Lock manager knows it expired"
There’s no one to stop the stale client from writing bad data.
Another instance grabs the same lock and processes the payment again.
When your original process wakes up, it still thinks it holds the lock — and charges the customer twice.
Another instance grabs the same lock and processes the payment again.
When your original process wakes up, it still thinks it holds the lock — and charges the customer twice.
Your service acquires a Redis lock with a 30-second TTL to process a payment.
Looks safe, right?
But then the JVM GC or network connection pauses for 35 seconds… 🧟
Your service acquires a Redis lock with a 30-second TTL to process a payment.
Looks safe, right?
But then the JVM GC or network connection pauses for 35 seconds… 🧟