State Locking

State locking prevents concurrent modifications to your Terraform state, avoiding corruption and conflicts when multiple team members or CI/CD systems are working with the same infrastructure.

How State Locking Works

When Terraform performs operations that could modify state (like apply, destroy, or import), it automatically acquires a lock on the state file. This ensures only one operation can modify the state at a time.

Lock Lifecycle

  1. Acquire: Terraform requests a lock before state-modifying operations
  2. Validate: FreeState checks if the state is already locked
  3. Grant/Deny: Lock is granted if available, denied if already held
  4. Operate: Terraform performs the requested operation
  5. Release: Lock is automatically released when operation completes

Lock Configuration

Backend Configuration

FreeState supports locking out of the box with the HTTP backend:

terraform {
  backend "http" {
    address        = "https://api.freestate.cloud/terraform/state"
    username       = "your-workspace-id"
    password       = "your-api-key"
    
    # Lock configuration
    lock_address   = "https://api.freestate.cloud/terraform/state/lock"
    lock_method    = "POST"
    unlock_address = "https://api.freestate.cloud/terraform/state/lock"
    unlock_method  = "DELETE"
  }
}

Lock Timeout Settings

Configure how long locks are held and when they timeout:

# In your workspace settings
lock_timeout = "15m"        # Maximum lock duration
auto_unlock = true          # Auto-unlock after timeout
lock_retry_delay = "30s"    # Delay between lock attempts

Lock Information

Lock Metadata

Each lock contains important metadata:

  • Lock ID: Unique identifier for the lock
  • Operation: Type of operation (apply, destroy, etc.)
  • User: Who acquired the lock
  • Timestamp: When the lock was acquired
  • Version: Terraform version being used
  • Path: Terraform working directory

Viewing Lock Status

# Check if state is locked
terraform plan

# If locked, you'll see output like:
# Error: Error locking state: Error acquiring the state lock: 
# ConditionalCheckFailedException: Lock Info:
#   ID:        1234567890abcdef
#   Path:      /path/to/terraform
#   Operation: OperationTypePlan
#   Who:       user@example.com
#   Version:   1.6.0
#   Created:   2024-01-15 10:30:00 UTC

Working with Locked States

When State is Locked

If you encounter a locked state:

1. Wait for Operation to Complete

The most common scenario - another operation is in progress:

# Wait and retry
terraform plan

# Or check workspace activity in dashboard

2. Contact the Lock Holder

If the lock is held by another team member:

  • Check who has the lock from the error message
  • Contact them to coordinate
  • Wait for them to complete their operation

3. Force Unlock (Use with Caution)

Only use force unlock if you're certain the lock holder has crashed or is no longer running:

# Force unlock using the Lock ID from the error message
terraform force-unlock 1234567890abcdef

# Confirm when prompted
# Do you really want to force-unlock?
#   Only 'yes' will be accepted to confirm.
# 
#   Enter a value: yes

⚠️ Force Unlock Warning

Only force unlock if you're absolutely certain no other Terraform operation is running. Force unlocking while another operation is active can lead to state corruption.

Lock Monitoring and Notifications

Dashboard Monitoring

Monitor lock activity in your FreeState dashboard:

  • Current lock status for each workspace
  • Lock history and duration
  • Failed lock attempts
  • Automatic unlock events

Webhook Notifications

Set up webhooks to get notified of lock events:

# Webhook payload example
{
  "event": "lock.acquired",
  "workspace": "my-app-prod",
  "lock_id": "1234567890abcdef",
  "user": "user@example.com",
  "operation": "apply",
  "timestamp": "2024-01-15T10:30:00Z"
}

Slack Integration

Get real-time lock notifications in Slack:

  1. Go to workspace settings
  2. Enable Slack integration
  3. Configure notification preferences
  4. Test notifications

CI/CD and Automation

GitHub Actions Example

name: Terraform Apply
on:
  push:
    branches: [main]

jobs:
  terraform:
    runs-on: ubuntu-latest
    timeout-minutes: 30  # Prevent indefinite hangs
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2
        
      - name: Terraform Init
        env:
          TF_HTTP_USERNAME: ${{ secrets.FREESTATE_WORKSPACE_ID}}
          TF_HTTP_PASSWORD: ${{ secrets.FREESTATE_API_KEY}}
        run: terraform init
        
      - name: Terraform Apply
        env:
          TF_HTTP_USERNAME: ${{ secrets.FREESTATE_WORKSPACE_ID}}
          TF_HTTP_PASSWORD: ${{ secrets.FREESTATE_API_KEY}}
        run: terraform apply -auto-approve
        
      # The lock is automatically released when the job completes

Handling Lock Failures in CI/CD

# Add retry logic for lock contention
- name: Terraform Apply with Retry
  env:
    TF_HTTP_USERNAME: ${{ secrets.FREESTATE_WORKSPACE_ID}}
    TF_HTTP_PASSWORD: ${{ secrets.FREESTATE_API_KEY}}
  run: |
    for i in {1..5}; do
      if terraform apply -auto-approve; then
        break
      else
        if [ $i -lt 5 ]; then
          echo "Lock contention, retrying in 30 seconds..."
          sleep 30
        else
          echo "Failed after 5 attempts"
          exit 1
        fi
      fi
    done

Best Practices

Lock Hygiene

  • Keep operations short: Minimize lock duration
  • Coordinate with team: Communicate before long-running operations
  • Use automation: CI/CD pipelines handle locks automatically
  • Monitor lock usage: Track patterns and bottlenecks

Team Coordination

  • Scheduled maintenance: Coordinate major infrastructure changes
  • Lock notifications: Set up team notifications for long locks
  • Emergency procedures: Define when force unlock is acceptable
  • Documentation: Document lock policies and procedures

CI/CD Integration

  • Set timeouts: Prevent jobs from hanging indefinitely
  • Implement retry logic: Handle temporary lock contention
  • Sequential workflows: Avoid parallel operations on same state
  • Lock before planning: Consider locking during plan phase

Troubleshooting Lock Issues

Stale Locks

If a lock appears to be held indefinitely:

  1. Check if the operation is actually running
  2. Look for crashed processes or terminated sessions
  3. Review lock timeout settings
  4. Consider enabling auto-unlock

Lock Contention

When multiple operations compete for locks:

  • Stagger CI/CD pipeline schedules
  • Use workspace isolation for parallel work
  • Implement exponential backoff in automation
  • Consider read-only operations during peak times

Performance Issues

If lock operations are slow:

  • Check network connectivity to FreeState
  • Review API rate limiting
  • Contact support for performance analysis

Advanced Lock Features

Lock Inheritance

Locks are inherited across related operations:

  • Plan operations can share read locks
  • Apply operations require exclusive write locks
  • Import operations require write locks

Lock Analytics

FreeState provides detailed lock analytics:

  • Average lock duration by operation type
  • Peak usage times and bottlenecks
  • User and automation patterns
  • Failed lock attempts and reasons

Custom Lock Policies

Configure workspace-specific lock policies:

  • Maximum lock duration limits
  • Auto-unlock thresholds
  • User-specific lock permissions
  • Emergency unlock procedures