Calculate an appropriate state lock timeout based on team size and apply frequency.
Formula: timeout = expected_apply_time × safety_factor. Setting `-lock-timeout` (or your backend's equivalent) too low causes spurious 'state locked' failures when a legitimate apply is simply still running; setting it too high means a genuinely stuck/crashed process holds the lock for a long time before anyone notices. The safety factor buys margin for applies that run longer than typical without masking real stale-lock problems indefinitely.
lock_timeout_min = expected_apply_minutes × safety_factor
A stale lock happens when a process acquires the state lock (e.g. via DynamoDB for S3 backends) but crashes, gets killed, or loses network connectivity before releasing it — the lock then blocks all future applies until manually cleared.
As a last resort, `terraform force-unlock <LOCK_ID>` removes the lock — but only do this after confirming no apply is genuinely still running, since forcing an unlock during an active apply can corrupt state.
For infrastructure changes, queuing (retrying until the timeout) is usually safer than failing fast, since it avoids partial applies from a canceled run — but very long queues suggest you need fewer concurrent pipelines targeting the same state.
Splitting a monolithic configuration into workspaces/root modules with independent state files eliminates most lock contention entirely, since unrelated changes no longer compete for the same lock.