Server¶
Running the server¶
# Default: listens on 127.0.0.1:6388
./dflockd
# Custom port
./dflockd --port 7000
# Multiple options
./dflockd --host 127.0.0.1 --port 7000 --max-locks 512
# Debug logging
./dflockd --debug
CLI flags¶
| Flag | Default | Description |
|---|---|---|
--host |
127.0.0.1 |
Bind address |
--port |
6388 |
Bind port |
--default-lease-ttl |
33 |
Default lock lease duration (seconds) |
--lease-sweep-interval |
1 |
How often to check for expired leases (seconds) |
--gc-interval |
5 |
How often to prune idle lock state (seconds) |
--gc-max-idle |
60 |
Seconds before idle lock state is pruned |
--max-locks |
1024 |
Maximum number of unique lock keys |
--max-connections |
0 |
Maximum concurrent connections (0 = unlimited) |
--max-waiters |
0 |
Maximum waiters per lock/semaphore key (0 = unlimited) |
--read-timeout |
23 |
Client read timeout (seconds) |
--write-timeout |
5 |
Client write timeout (seconds) |
--shutdown-timeout |
30 |
Graceful shutdown drain timeout (seconds, 0 = wait forever) |
--tls-cert |
(unset) | Path to TLS certificate PEM file |
--tls-key |
(unset) | Path to TLS private key PEM file |
--auth-token |
(unset) | Shared secret for client authentication (visible in process list; prefer --auth-token-file) |
--auth-token-file |
(unset) | Path to file containing the auth token (one line, trailing whitespace stripped) |
--auto-release-on-disconnect / --no-auto-release-on-disconnect |
true |
Release locks when a client disconnects |
--debug |
false |
Enable debug logging |
Environment variables¶
All settings can be configured via environment variables. Environment variables take precedence over CLI flags.
| Variable | Default | Description |
|---|---|---|
DFLOCKD_HOST |
127.0.0.1 |
Bind address |
DFLOCKD_PORT |
6388 |
Bind port |
DFLOCKD_DEFAULT_LEASE_TTL_S |
33 |
Default lock lease duration (seconds) |
DFLOCKD_LEASE_SWEEP_INTERVAL_S |
1 |
How often to check for expired leases |
DFLOCKD_GC_LOOP_SLEEP |
5 |
How often to prune idle lock state |
DFLOCKD_GC_MAX_UNUSED_TIME |
60 |
Seconds before idle lock state is pruned |
DFLOCKD_MAX_LOCKS |
1024 |
Maximum number of unique lock keys |
DFLOCKD_MAX_CONNECTIONS |
0 |
Maximum concurrent connections (0 = unlimited) |
DFLOCKD_MAX_WAITERS |
0 |
Maximum waiters per lock/semaphore key (0 = unlimited) |
DFLOCKD_READ_TIMEOUT_S |
23 |
Client read timeout (seconds) |
DFLOCKD_WRITE_TIMEOUT_S |
5 |
Client write timeout (seconds) |
DFLOCKD_SHUTDOWN_TIMEOUT_S |
30 |
Graceful shutdown drain timeout (seconds, 0 = wait forever) |
DFLOCKD_TLS_CERT |
(unset) | Path to TLS certificate PEM file |
DFLOCKD_TLS_KEY |
(unset) | Path to TLS private key PEM file |
DFLOCKD_AUTH_TOKEN |
(unset) | Shared secret for client authentication |
DFLOCKD_AUTH_TOKEN_FILE |
(unset) | Path to file containing the auth token |
DFLOCKD_AUTO_RELEASE_ON_DISCONNECT |
1 |
Release locks when a client disconnects |
DFLOCKD_DEBUG |
(unset) | Enable debug logging (1, yes, or true) |
# Example: configure via environment
export DFLOCKD_PORT=7000
export DFLOCKD_MAX_LOCKS=2048
./dflockd
Tuning guide¶
Lease TTL¶
The default-lease-ttl controls how long a lock is held before it expires if not renewed. Clients are responsible for sending renew (n) commands before the lease expires.
- Shorter TTL (e.g. 10s): faster failover when clients crash, but more renewal traffic.
- Longer TTL (e.g. 60s): less renewal traffic, but slower failover.
Max locks¶
The max-locks setting caps the total number of unique lock keys and semaphore keys tracked by the server. Lock keys and semaphore keys share the same budget. When the limit is reached, new lock or semaphore requests for unknown keys return error_max_locks. Existing keys are unaffected.
Garbage collection¶
Idle lock state (no owner, no waiters) is pruned after gc-max-idle seconds. The GC runs every gc-interval seconds. For workloads with many transient keys, lower gc-max-idle to reclaim memory faster.
Read timeout¶
The read-timeout controls how long the server waits for a client to send a complete request line. Idle connections that send no data within this window are disconnected. This prevents resource exhaustion from abandoned connections.
Write timeout¶
The write-timeout controls how long the server waits for a response write to complete. If a client is reading slowly (or not at all), the write will fail after this deadline and the connection is closed. This prevents slow-reading clients from blocking server goroutines indefinitely.
Shutdown timeout¶
The shutdown-timeout controls the maximum time the server waits for active connections to finish during graceful shutdown (SIGINT/SIGTERM). When the timeout expires, any remaining connections are force-closed.
- Default (30s): suitable for most workloads. Gives clients time to finish in-flight operations.
- Shorter timeout (e.g. 5s): faster shutdown, useful in container orchestration where a SIGKILL follows after a grace period.
- Longer timeout (e.g. 120s): for workloads with long-running lock acquisitions.
- 0: wait forever (no deadline). The server blocks until all clients disconnect naturally. This matches pre-1.8.0 behavior.
Max connections¶
The max-connections setting caps the total number of concurrent TCP connections. When the limit is reached, new connections are accepted and immediately closed. Set to 0 (the default) for unlimited connections.
Max waiters¶
The max-waiters setting caps the number of pending waiters per key for both locks and semaphores. When the limit is reached, new acquire or enqueue requests for that key return error_max_waiters. This prevents unbounded memory growth from waiter queues on a single contended key. Set to 0 (the default) for unlimited waiters.
Auto release on disconnect¶
When DFLOCKD_AUTO_RELEASE_ON_DISCONNECT is enabled (the default), the server automatically releases any locks held by a client when its TCP connection closes — whether gracefully or due to a crash. Pending waiters from that connection are also cancelled. The released lock is transferred to the next FIFO waiter, if any.
Accepts 1, yes, or true (case-insensitive) to enable; any other value disables it.
# Disable auto-release (locks persist until lease expiry)
export DFLOCKD_AUTO_RELEASE_ON_DISCONNECT=0
Warning
Disabling this means locks from disconnected clients will only be freed when their lease expires. This increases the window where a lock is held by a dead client.
TLS¶
To enable TLS encryption, provide both a PEM certificate and private key file:
Or via environment variables:
Both --tls-cert and --tls-key must be provided together. If only one is set, the server exits with an error. When TLS is enabled, the server requires all clients to connect using TLS — plain TCP connections will fail the TLS handshake and be dropped.
The server enforces a minimum TLS version of 1.2.
Authentication¶
To require token-based authentication, set a shared secret:
Or load the token from a file (avoids leaking the secret in the process list):
Or via environment variables:
export DFLOCKD_AUTH_TOKEN=my-secret-token
./dflockd
# or
export DFLOCKD_AUTH_TOKEN_FILE=/run/secrets/dflockd-token
./dflockd
Token resolution priority: DFLOCKD_AUTH_TOKEN env var > --auth-token flag > --auth-token-file flag > DFLOCKD_AUTH_TOKEN_FILE env var.
When --auth-token is set, every new connection must send an auth command as its first message. If the token matches, the server responds with ok and the connection proceeds normally. If the token is wrong or a non-auth command is sent first, the server responds with error_auth and closes the connection.
If --auth-token is not set (the default), no authentication is required and all connections are accepted as before.
The token comparison uses constant-time comparison (crypto/subtle.ConstantTimeCompare) to prevent timing attacks.
Warning
The auth token is sent in plaintext over the wire. Use together with TLS (--tls-cert / --tls-key) to protect the token in transit.
Runtime stats¶
The stats protocol command returns a JSON snapshot of the server's current state. This is useful for monitoring, debugging, and building health checks.
printf 'stats\n_\n\n' | nc localhost 6388
# ok {"connections":2,"locks":[...],"semaphores":[...],"idle_locks":[],"idle_semaphores":[]}
The response includes:
- connections — number of currently connected TCP clients
- locks — held locks with key, owner connection ID, seconds until lease expires, and waiter count
- semaphores — semaphores with at least one holder, showing key, limit, holder count, and waiter count
- idle_locks / idle_semaphores — entries with no owner/holders (cached state awaiting GC), with seconds since last activity
See Wire Protocol for the full JSON schema.