---
layout: commands
page_title: 'Commands: Lock'
description: >-
  The lock command provides a mechanism for leader election, mutual exclusion,
  or worker pools. For example, this can be used to ensure a maximum number of
  services running at once across a cluster.
---

# Consul Lock

Command: `consul lock`

The `lock` command provides a mechanism for simple distributed locking.
A lock (or semaphore) is created at a given prefix in the KV store,
and only when held, is a child process invoked. If the lock is lost or
communication is disrupted, the child process is terminated.

The number of lock holders is configurable with the `-n` flag. By default,
a single holder is allowed, and a lock is used for mutual exclusion. This
uses the [leader election algorithm](/consul/docs/automate/application-leader-election).

If the lock holder count is more than one, then a semaphore is used instead.
A semaphore allows more than a single holder, but this is less efficient than
a simple lock. This follows the [semaphore algorithm](/consul/tutorials/developer-configuration/distributed-semaphore).

To apply a lock to a remote WAN federated datacenter, run the command with the `-datacenter=<name>` flag on a server agent. You cannot use the command with `-datacenter` on client agents because they are unavailable to the remote datacenter.

All locks using the same prefix must agree on the value of `-n`. If conflicting
values of `-n` are provided, an error will be returned.

An example use case is for highly-available N+1 deployments. In these
cases, if N instances of a service are required, N+1 are deployed and use
consul lock with `-n=N` to ensure only N instances are running. For singleton
services, a hot standby waits until the current leader fails to take over.

## Usage

Usage: `consul lock [options] prefix child...`

The only required options are the key prefix and the command to execute.
The prefix must be writable. The child is invoked only when the lock is held,
and the `CONSUL_LOCK_HELD` environment variable will be set to `true`.

If the lock is lost, communication is disrupted, or the parent process
interrupted, the child process will receive a `SIGTERM`. After a grace period
of 5 seconds, a `SIGKILL` will be used to force termination. For Consul agents
on Windows, the child process is always terminated with a `SIGKILL`, since
Windows has no POSIX compatible notion for `SIGTERM`.

#### Command Options

- `-child-exit-code` - Exit 2 if the child process exited with an error
  if this is true, otherwise this doesn't propagate an error from the
  child. The default value is false.

- `-monitor-retry` - Retry up to this number of times if Consul returns a 500 error
  while monitoring the lock. This allows riding out brief periods of unavailability
  without causing leader elections, but increases the amount of time required
  to detect a lost lock in some cases. Defaults to 3, with a 1s wait between retries.
  Set to 0 to disable.

- `-n` - Optional, limit of lock holders. Defaults to 1. The underlying
  implementation switches from a lock to a semaphore when increased past
  one. All locks on the same prefix must use the same value.

- `-name` - Optional name to associate with the underlying session.
  If not provided, one is generated based on the child command.

- `-shell` - Optional, use a shell to run the command (can set a custom shell via the
  SHELL environment variable). The default value is true.

- `-pass-stdin` - Pass stdin to child process.

- `-timeout` - Attempt to acquire the lock up to the given timeout. The timeout is a
  positive decimal number, with unit suffix, such as "500ms". Valid time units
  are "ns", "us" (or "µs"), "ms", "s", "m", "h". The default value is 0.

- `-verbose` - Enables verbose output.

#### API Options

@include 'legacy/http_api_options_client.mdx'

@include 'legacy/http_api_options_server.mdx'

## Node health checks and TTL behavior

When you run `consul lock`, Consul automatically creates an _ephemeral session_ that attaches one or more node checks, such as the `serfHealth` check, by default. These checks keep the node “healthy” from Consul’s perspective. This session automatically renews as long as the agent passes these health checks. For sessions with a a TTL configured, that TTL never reaches zero as long as the node remains healthy.

This design ensures the lock is not lost as long as the local Consul agent is up and healthy. However, emphemeral sessions run indefinitely when:

- **The node remains healthy**, including in partial networks where at least one Consul server still reads the node as online.  
- **No explicit session destroy** or forced release occurs.

To strictly enforce the TTL and prevent auto-renewed by node checks, you must create or manage your own session separately. In that scenario:

1. **Manually create a session** with the HTTP API that either excludes node checks or uses custom service checks.  
1. **Acquire the lock** on that custom session using the raw KV API (`?acquire=<sessionID>`).  
1. **Manage renewals** and releases yourself as needed.

When you remove node checks, the TTL-based session expires after the specified time if you do not renew it. Consul releases the lock automatically when the session expires.

## Node health checks and TTL behavior

When you run `consul lock`, Consul automatically creates an _ephemeral session_ that attaches one or more node checks, such as the `serfHealth` check, by default. These checks keep the node “healthy” from Consul’s perspective. This session automatically renews as long as the agent passes these health checks. For sessions with a a TTL configured, that TTL never reaches zero as long as the node remains healthy.

This design ensures the lock is not lost as long as the local Consul agent is up and healthy. However, emphemeral sessions run indefinitely when:

- **The node remains healthy**, including in partial networks where at least one Consul server still reads the node as online.  
- **No explicit session destroy** or forced release occurs.

To strictly enforce the TTL and prevent auto-renewed by node checks, you must create or manage your own session separately. In that scenario:

1. **Manually create a session** with the HTTP API that either excludes node checks or uses custom service checks.  
1. **Acquire the lock** on that custom session using the raw KV API (`?acquire=<sessionID>`).  
1. **Manage renewals** and releases yourself as needed.

When you remove node checks, the TTL-based session expires after the specified time if you do not renew it. Consul releases the lock automatically when the session expires.

## SHELL

Consul lock launches its children in a shell. By default, Consul will use the shell
defined in the environment variable `SHELL`. If `SHELL` is not defined, it will
default to `/bin/sh`. It should be noted that not all shells terminate child
processes when they receive `SIGTERM`. Under Ubuntu, `/bin/sh` is linked to `dash`,
which does **not** terminate its children. In order to ensure that child processes
are killed when the lock is lost, be sure to set the `SHELL` environment variable
appropriately, or run without a shell by setting `-shell=false`.
