Representative interview topic

General Interview: How Would You Design a Recoverable HTTP 423 Locked Resource Lock?

GeneralHard
Offer.cc Editorial TeamPublished Updated

Question

A collaborative file service sometimes returns HTTP 423 Locked. Explain the protocol boundary of 423, lock-token validation, expiry and owner-crash recovery, and how to avoid treating a lock as an unlimited business state.

Prompt and scope

A collaborative file service supports WebDAV and lets clients edit the same resource. Writes, moves, or deletes sometimes return 423 Locked. Explain the boundary between 423, 409, and 403; how clients obtain and submit a lock token; how to handle depth, timeout, renewal, and owner crashes; and how to make recovery observable.

What the interviewer is testing

  • Whether you explain 423 as a lock blocking the target resource instead of a generic concurrency error.
  • Whether you understand Lock-Token, If, Timeout, and UNLOCK together.
  • Whether you can design leases, reconnect recovery, and authorization without permanent locks or accidental unlocks.
  • Whether clients can distinguish waiting, reacquiring, and non-retryable failures.

Questions to clarify first

  1. Is the lock a WebDAV write lock, an application editing lease, or both?
  2. Does it cover one resource or an infinity-depth collection, and how do children inherit or opt out?
  3. Where is the token stored, and is it bound to tenant, principal, resource version, and permission?
  4. Who renews and reclaims it after disconnects, process crashes, or clock skew?
  5. Can a proxy retry writes, and can the client safely replay the body?

A 30-second answer

423 says a lock currently prevents the method from applying to the target; it is not a generic permission denial or every version conflict. I would establish the scope, owner, and remaining lease, then require the matching Lock-Token in the If condition. The service owns the lease and uses monotonic time; renewal is authorized and bounded, while expiry reclaims the lock after a crash. The client treats 423 as controlled waiting or reacquisition, never blindly replaying a non-idempotent write.

Step-by-step deep dive

Step 1: Define the protocol boundary

RFC 4918 uses 423 when a method cannot be applied to a locked resource. 403 is about authorization and 409 about a conflict with current state, so classify the blocking cause before choosing the status.

Step 2: Define lock identity and scope

Store the resource identity, lock root, depth, owner, token, creation time, lease, permission domain, and resource version. An infinity-depth lock can cover children, so the server resolves inheritance before every write instead of checking only the URL.

Step 3: Validate Lock-Token

The client obtains a token with LOCK and sends it in the If condition on later write, move, or delete requests. The server checks token, scope, principal, and tenant. Missing, malformed, or foreign tokens receive a diagnosable failure without exposing another tenant’s owner.

Step 4: Use leases for timeout and renewal

Timeout is a requested value, not permission for the client to create an unlimited lease. The server stores expiry using a monotonic clock, authenticates renewal, and caps the maximum duration. The response states the granted timeout, and the client schedules renewal from that value. Expiry reclaims the lock after a crash.

Step 5: Handle disconnect and recovery

After reconnecting, an owner queries lock state and renews only with a still-valid token; local cache cannot prove ownership. A restart restores leases from durable storage. If safe restoration cannot be proven, invalidate the lock and require reacquisition so an old token cannot write.

Step 6: Separate waiting from retrying

The client can show a holder-agnostic “resource is being edited” state and poll with backoff based on the remaining lease. 423 is not a transient network failure. Retry a write only when token, version, and body are confirmed replayable; proxies must not replay a non-idempotent request with an unknown execution result.

Step 7: Observe and constrain abuse

Record a resource hash, lock scope, remaining lease, failure reason, principal hash, and request ID. Measure 423 rate, hold duration, renewal failures, expiry reclamation, and depth-lock count by tenant, resource type, and client version. Limit depth-lock count, maximum lease, and token attempts to contain exhaustion and guessing.

High-quality sample answer

I would first prove that 423 is a WebDAV lock, separating it from 403 authorization and 409 application-state conflict. The lock service durably stores resource, depth, principal, tenant, Lock-Token, granted lease, and version. A client obtains the token with LOCK and submits it in If; the server validates token, scope, principal, and permission together. The lease uses server-side monotonic time and a maximum duration. After disconnect, the client can renew only with a valid token; after a crash, expiry reclaims the lock. The client presents a recoverable editing-occupied state, polls with backoff, and never blindly retries a write with an unknown result. Production telemetry covers 423 rate, hold duration, renewal failures, reclamation, and depth-lock count, with tests for competing clients, restart, clock skew, and proxy retries.

Common mistakes

  • Returning 423 for every concurrency conflict and hiding version or permission errors.
  • Keeping locks only in memory, creating permanent locks or wrongful unlocks after a crash.
  • Accepting an unlimited client Timeout instead of returning the granted lease.
  • Comparing only token strings without checking scope, tenant, and principal permission.
  • Letting a proxy replay a side-effecting write and applying it twice.

Follow-up questions and responses

When should you use 423 versus 409?

Use 423 when an effective lock blocks the method; use 409 when no lock exists but the request conflicts with current version or state. Both need a diagnosable recovery path.

How do you contain an infinity-depth lock?

Restrict its permission and count, resolve the inheritance chain to the target, and recompute coverage for move, copy, and delete. Explicitly reject cross-tenant or cross-collection operations instead of assuming inheritance.

Can an administrator force-unlock after a crash?

Only with explicit authority and an audit reason. Ordinary clients wait for expiry; a force unlock invalidates the old token and records operator, reason, and resource version.

What if server clocks disagree?

Use monotonic time at one node or in a consensus-backed store for expiry, and let clients rely on the granted remaining duration. Cross-node renewal needs a version condition so two nodes cannot extend one lock concurrently.

Public sources

Related questions