Terraform CI/CD: State locking issues during parallel PR plans

We are implementing a CI/CD workflow for our Genesys Cloud infrastructure using Terraform. The goal is straightforward: run terraform plan on every pull request to validate changes, and execute terraform apply only when the PR is merged into the main branch. We are using GitHub Actions for this.

The issue arises when multiple developers open PRs simultaneously. Each workflow runs in parallel, which causes state locking errors. We are using the Genesys Cloud provider with remote state stored in an S3 backend with DynamoDB for locking. The error message we receive is:

Error: Error acquiring the state lock
Reason: ConditionalCheckFailedException: The conditional request failed
Lock Info:
 ID: a1b2c3d4-5678-90ab-cdef-1234567890ab
 Path: gen/terraform.tfstate
 Operation: OperationTypePlan
 Who: user@example.com@runner-hostname
 Version: 1.5.0
 Created: 2023-10-27 10:00:00 +0000 UTC
 Info: 
```n

We have tried adding a `retry` mechanism in the GitHub Actions workflow, but that is not a clean solution. It feels like we are fighting the tool rather than configuring it correctly. The documentation mentions that state locking is designed to prevent concurrent modifications, but it does not provide clear guidance on how to handle parallel reads (plans) effectively.

Is there a recommended pattern for handling this? We considered using separate state files for each PR, but that seems to introduce complexity in managing dependencies and data sources that rely on existing resources. Another idea was to use a queueing system for plans, but that adds latency to the developer feedback loop.

We are currently on Terraform version 1.5.0 and the Genesys Cloud provider version 1.2.0. The environment is set up with standard IAM permissions for S3 and DynamoDB. Any insights on how to structure this workflow without running into locking issues would be appreciated.

State locking isn’t a Genesys API constraint, it’s a Terraform backend issue. If you’re using remote state, ensure your backend supports locking. S3 with DynamoDB works, but check your provider config. Local state won’t handle parallel runs.

backend "s3" {
 bucket = "my-terraform-state"
 dynamodb_table = "terraform-lock"
}