Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 20 – Building blocks: control, safety and platform services

Design a lock and coordination service

Design a lock and coordination service on a consensus log, with sessions, keepalives, watches, fencing tokens and clients that stop when sessions expire.

  • Advanced
  • 30 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free intro, Pro: 5 of 30 minutes free
Free: Requirements and estimate: keepalives, not locks, load the cell. With a pass: the other 15 sections and 3 interview answers, about 25 minutes.

What you will learn

  • Design a consensus-backed lock and lease service from requirements and a load estimate
  • Specify sessions, keepalives, waiter queues, watches and fencing tokens, with their error cases
  • Explain what a client library must do when its session is in doubt and when it has expired
  • Size one coordination cell for 120,000 client processes and decide when proxies and more cells are needed

Before you start

What you’ll learn · Before you start

What you will learn

  • Design a consensus-backed lock and lease service from requirements and a load estimate
  • Specify sessions, keepalives, waiter queues, watches and fencing tokens, with their error cases
  • Explain what a client library must do when its session is in doubt and when it has expired
  • Size one coordination cell for 120,000 client processes and decide when proxies and more cells are needed

Before you start

On this page

A lock and coordination service is a small, strongly consistent store that many processes use to agree on who holds a lock, who leads a group and what the current configuration is. It replicates every change through a consensus: Agreement among a group of servers on one ordered log of values, reached by majority vote, so that every committed value survives the failure of any minority of the servers. More in “Consensus in practice: what Raft gives you” group of about five servers, so it keeps working while a minority of them fail. Clients hold sessions that they keep alive with heartbeats; locks and membership keys belong to a session and vanish when it expires; watches tell clients when something changes; and every grant carries a fencing token: A number that rises every time a lease or leadership changes hands. The storage refuses a write that carries a lower token than one it has already accepted. More in “Failover, split brain and fencing” that the protected resource checks. Interviewers ask you to design a lock service to hear what pauses, partitions and failovers do to it. Chubby, ZooKeeper and etcd are the best-known examples.

Requirements and estimate: keepalives, not locks, load the cell

A company runs 2,000 services, each with about 60 processes spread over three zones of one region. Schedulers need one active leader per job, deploy tools take maintenance locks, every process announces that it is alive, and routing tables live in small configuration keys. Before you design a lock and coordination service for them, ask:

  • What will clients use it for: locks, leader election: Choosing one process out of several to do a job alone, usually through a coordination service, with a lease so that a crashed leader is replaced without anyone's help. More in “Leader election, leases and fencing tokens”, membership or configuration?
  • How many client processes are there, and how often does a lock change hands?
  • How quickly must a dead holder’s lock reach the next process?
  • Must every read see the latest write?
  • One region or several, and what should a client do when it cannot reach the service?

The answers here: 120,000 client processes, 5,000 locks that change hands about ten times a day each, a dead holder replaced within about 15 seconds, reads of lock state that are never stale, and one region with three zones.

Functional requirements: open and keep alive a session; acquire and release a lock, waiting in a queue; ephemeral keys that vanish with their session; watches on keys and prefixes; small keys with conditional writes; a fencing token with every grant. Non-functional requirements: never two holders as far as a resource that checks tokens can tell; survive the loss of any one zone; acquire within about 20 ms inside the region; and clients that stop acting as holders before the service can give their lock away.

The first estimate:

Sessions, keepalives, writes and watch events for one cell Python · plan/lock_estimate.py
# A first load estimate for the lock and coordination service of this lesson. Every input is an assumption to
# replace with numbers from your own fleet: the process count from your deploy system, handovers from the service's
# own logs, and watchers from how your client libraries use watches.
SERVICES = 2_000
PROCESSES_PER_SERVICE = 60      # one session each, 20 in each of 3 zones
ZONES = 3
TTL_S = 12                      # session lease
RENEWALS_PER_TTL = 3            # renew three times per lease, so one lost reply is not fatal
LOCKS = 5_000                   # locks and leader elections in use
HANDOVERS_PER_DAY = 10          # times a lock changes holder on a normal day
ENTRY_BYTES = 200               # a session, lock or membership key with its metadata
CONFIG_KEYS, CONFIG_BYTES = 10_000, 4_000

clients = SERVICES * PROCESSES_PER_SERVICE
keepalives = clients * RENEWALS_PER_TTL / TTL_S
writes = LOCKS * HANDOVERS_PER_DAY / 86_400
entries = clients + LOCKS + clients        # sessions, locks, one membership key per process
state_mb = (entries * ENTRY_BYTES + CONFIG_KEYS * CONFIG_BYTES) / 1e6

per_zone = PROCESSES_PER_SERVICE // ZONES
lost = SERVICES * per_zone                 # the sessions of the zone that fails
survivors = PROCESSES_PER_SERVICE - per_zone
events = lost * survivors                  # each survivor watches its own service's members

print(f"clients: {SERVICES:,} services x {PROCESSES_PER_SERVICE} processes = {clients:,} sessions")
print(f"keepalives: each renewed every {TTL_S // RENEWALS_PER_TTL} s = {keepalives:,.0f} a second, all at the leader")
print(f"normal writes: {LOCKS:,} locks x {HANDOVERS_PER_DAY} handovers a day = {writes:.1f} a second")
print(f"state: {entries:,} entries x {ENTRY_BYTES} B + {CONFIG_KEYS:,} config keys x {CONFIG_BYTES:,} B = {state_mb:.0f} MB")
print(f"one zone fails: {lost:,} sessions expire within {TTL_S} s = {lost / TTL_S:,.0f} expiry writes a second")
print(f"  about {round(LOCKS / ZONES):,} locks change holder; {events:,} membership watch events reach the survivors")

Output

clients: 2,000 services x 60 processes = 120,000 sessions
keepalives: each renewed every 4 s = 30,000 a second, all at the leader
normal writes: 5,000 locks x 10 handovers a day = 0.6 a second
state: 245,000 entries x 200 B + 10,000 config keys x 4,000 B = 89 MB
one zone fails: 40,000 sessions expire within 12 s = 3,333 expiry writes a second
  about 1,667 locks change holder; 1,600,000 membership watch events reach the survivors

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 lock_estimate.py

The locks are the smallest load, well under one write a second. Keepalives, 30,000 a second, all land on the leader, and the loss of one zone turns into 3,333 expiry writes a second and 1.6 million watch events. The whole state fits in memory on every server.

Checkpoint

Check the estimate

  1. Question 1 of 2 50,000 client processes hold sessions with a 10-second lease, each renewed twice per lease. How many keepalives a second reach the leader?

    Type a number.

    Show the answer: Question 1 of 2

    Answer: 10000 keepalives a second

    Each session renews every 10 ÷ 2 = 5 seconds, so 50,000 ÷ 5 = 10,000 keepalives a second, all at the leader, however few locks change hands.

  2. Question 2 of 2 A zone that held 30,000 sessions fails, and they all expire within one 10-second lease. If each expiry is its own log entry, how many expiry writes a second must the log absorb?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 3000 writes a second

    30,000 ÷ 10 = 3,000 expiry entries a second, against well under one write a second for the locks on a normal day. A failure, not the steady state, sets the peak write load.

Clients keep sessions with a five-server cell in three zones and write to a resource with tokens; one state machine per server.Application sideCell: 5 servers in 3 zonesState machine on every server:sessions, waiter queues,keys with revisions, watches120,000 clients:sessions, keepalives,own deadlinesProtectedresource: refusesolder tokensZone A:leader,followerZone B:2 followersZone C:1 followertokensessions, locks, watchesentries in log order

The first design of the lock and coordination service

Text description of the diagram

The diagram shows the first design from top to bottom.

  • At the top is the application side. On the left are 120,000 client processes; each keeps a session, sends keepalives and tracks its own lease deadline. On the right is a protected resource. A dashed arrow from the clients to the resource shows that every write carries the holder's fencing token, and the resource refuses tokens older than one it has seen.
  • An arrow from the application side down to the cell carries sessions, lock requests and watches.
  • In the middle is the coordination cell: five servers in three zones, the leader and a follower in zone A, two followers in zone B and one follower in zone C.
  • An arrow from the cell down to the bottom box shows the committed log entries, applied in log order.
  • At the bottom is the state machine that every server keeps: sessions, waiter queues, keys with their revisions, and watches.

Follow one lock through the cell:

Interactive · message by message One lock through the cell Step through client A taking a lock, client B queuing behind it, and the hand-over when A releases it.
One lock through the cell, step 7 of 7. Messages so far: Client A to Cell leader: open session; Client A to Cell leader: acquire jobs/leader; Cell leader to Client A: held, token 7; Client B to Cell leader: acquire jobs/leader; Client A to Cell leader: release; Cell leader to Client B: held, token 8.Client Ano lockCell leaderlog on 5 servers, 3 zonesClient Bholds the lock, token 8open sessionacquire jobs/leaderheld, token 7acquire jobs/leaderreleaseheld, token 8

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. A session. Client A opens a session with a lease of 12 seconds and keeps it alive with keepalives. Everything it holds will belong to that session.
  2. Asking for the lock. A asks for the lock jobs/leader. The leader appends the request to its log, and once a majority of the five servers has stored the entry, every server applies it in the same order.
  3. A holds it. Nobody was waiting, so A holds the lock, and the reply carries a fencing token, 7. Every write A sends to the protected resource carries that number.
  4. B waits. Client B asks for the same lock. It joins the queue of waiters, as one entry, and watches only the entry just ahead of it, A's.
  5. A releases. A finishes and releases the lock. Deleting its entry is a log entry too, so every server sees the release at the same point in the log.
  6. The watch fires. B's watch fires, and B now holds the lock with token 8, larger than any token handed out before it.
  7. The resource decides. A resource that has accepted a write with token 8 refuses any later write that still carries 7, so a slow message from A can never overwrite B's work.

The choices still open, each with its plain meaning:

  • A replicated log: every change becomes an entry that a majority of servers stores before any server applies it.
  • Sessions with keepalives: a client proves that it is alive by renewing a lease: A time-limited right to act, as a leader or as the holder of a lock. The holder may act only while the lease lasts, and no successor starts before it has expired. More in “Failover, split brain and fencing” on its session.
  • Ephemeral keys: keys that the service deletes when the session that created them ends.
  • Waiter queues: each waiting client owns one entry and watches the entry just ahead of it.
  • Fencing tokens: a number that grows with every grant, which the protected resource checks.
  • Watches: notifications of changes to a key or a prefix, resumable from a revision.
  • A grace period: time a client waits without acting before it gives up on its session.
  • Proxies: servers that carry many clients’ sessions to the cell as a few.

The deep dives that decide whether this design works:

  1. What does each call write to the log, and where does the fencing token come from?
  2. How long should a session last, and what must a client do when it stops hearing from the service?
  3. What happens to sessions and locks when the leader fails?
  4. How do 200 clients wait for one lock without a stampede, and what if the reply to an acquire is lost?
  5. How are reads kept up to date without sending every read through the log?
  6. How does one cell serve 120,000 processes, and where does it stop scaling?

An answer is judged on requirements and estimates, the replicated state machine, sessions and expiry, client behaviour during failures, fencing, and scaling.

The holder’s create revision is its fencing token Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • Every change is a log entry, except keepalives
  • A cut-off holder, a herd and a lost reply, simulated
  • A client rides out a failover with jeopardy, a grace period and lease extension
  • A watch resumes from a revision, or reads the state again
  • Reads that are never stale, and reads that may be
  • Keepalives size a cell: longer leases, proxies and observers
  • Failure drills: a lost leader, a slow disk, a lost zone, a paused client
    • The leader crashes at peak
    • The leader’s disk becomes slow
    • A zone is cut off
    • A client pauses or its clock jumps
  • Bottlenecks at 10× and 100×
  • Alternatives rejected
  • What each level is expected to cover
  • A sample answer and a 45-minute self-mock
  • Practise: a lock table with sessions and tokens
    • Keep a lock table with sessions, waiters and fencing tokens
  • Interview questions
    • Your coordination service runs five servers for 60,000 client processes with 10-second sessions. After a deploy doubled the number of processes, the leader started missing heartbeats and elections now repeat every few minutes, although lock traffic did not change. What is overloading the leader, and how do you fix it without weakening safety?
    • Your coordination service's leader failed and a new one was elected after 15 seconds; sessions last 12 seconds. Thousands of services then lost their leaders at once, opened new sessions and queued for their locks again, and the new leader was overloaded for minutes. Explain what happened and how the service and its client library should behave.
    • One lock in your coordination service has 3,000 waiting clients. Every release makes the cell's CPU spike and other calls time out, and twice the lock stayed held after its holder had finished. How are the waiters probably implemented, and how would you redesign acquiring and waiting?
  • Key takeaways

3 diagrams · 4 runnable examples (JavaScript, Python) · 1 exercise with sample tests · 3 interview answers · about 61 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Rate-limiting algorithms compared

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.