GistPin uses Terraform with an S3 backend and DynamoDB locking for state management. State files are stored in versioned S3 buckets with encryption enforced.
| Bucket | Purpose |
|---|---|
gistpin-state-{env} |
Primary Terraform state storage |
gistpin-tf-access-logs-{env} |
S3 access logging for state bucket |
gistpin-terraform-state-{env} |
Legacy/provisioning state storage |
State keys follow the pattern: gistpin/terraform.tfstate
DynamoDB table gistpin-state-locks-{env} manages concurrent access. The lock table uses:
- PAY_PER_REQUEST billing mode
- Server-side encryption enabled
- Point-in-time recovery enabled
# Remove stale lock (use cautiously)
terraform force-unlock <LOCK_ID>- Noncurrent state versions expire after 90 days
- Incomplete multipart uploads abort after 7 days
- Access logs retained for 365 days
- Old state versions retained for audit and recovery
- Identify the last known good state version in S3:
aws s3api list-object-versions --bucket gistpin-state-staging \
--prefix gistpin/terraform.tfstate- Restore to a specific version:
aws s3api get-object --bucket gistpin-state-staging \
--key gistpin/terraform.tfstate \
--version-id <VERSION_ID> \
restored.tfstate- Push restored state:
terraform state push restored.tfstatebash infrastructure/scripts/migrate-state.sh migrate path/to/new-backend.tf# Backup existing state
terraform state pull > backup.tfstate
# Re-initialize with new backend
terraform init -migrate-state- Never edit
.tfstatefiles manually - Always enable versioning on state buckets
- Use DynamoDB locking in all environments
- Run
terraform planbeforeterraform apply - Store sensitive output in AWS Secrets Manager, not state
- Regularly audit state with
validate-state.sh