Terraform state lockはS3だけでOK

Terraform state lockはS3のConditional Writesで十分になっていた話

Terraform state lockは昔DynamoDBが必要でしたが、現在はS3のConditional Writesで十分になりました。
CodexにTerraformのコードを書いてもらった時にDynamoDB付きのコードが出てきたので、この話を思い出してメモしておこうと思いました。

経緯1 昔はDynamoDBが必要だった

Terraform backend S3の場合、backend "s3" ブロック内の dynamodb_table = "tfstate-lock" のような引数でDynamoDBを指定する必要がありました。
以下のようなコードを書いていました。

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "path/to/my/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "tfstate-lock"
    encrypt        = true
  }
}

そもそもterraformのstate lockってなんでしょうか?
State: Locking - v1.14.x docs を読むと、State lockingはTerraformのstateに書き込み処理をするような操作全てで起こり、State lockingが失敗するとTerraformは処理を継続しないと書かれています。Terraformのstateは同時に2つ以上のwrite操作で触ると壊れてしまうので、複数人で開発する場合やCI/CDでTerraformのwrite操作を行っている場合はstate lockが必要になります。

State lockingしない時に何が起こるかは TerraformのState Lockについて触ってみた(AWS, Terraform v1.11) - NRIネットコムBlog が分かりやすかったです。具体的にはリソースが2個できちゃったり、stateファイルに片方しか記録されなかったりします。

DynamoDBは、write操作の開始時にあらかじめテーブルにロック用のアイテムを作成しておいて、終了時に削除することでstate lockの制御を実装していました。他のwrite操作が来ると既にアイテムがあるのでエラーになる、という仕組みです。
この辺りは terraform のロック制御に DynamoDB が必要な理由 を読むと良いです。

経緯2 S3がConditional Writesをサポートした

2024/8/20に、S3でのConditional Writesのサポートが発表されました。これは以下のような内容です。(抜粋)

Amazon S3 adds support for conditional writes that can check for the existence of an object before creating it.

To use conditional writes, you can add the HTTP if-none-match conditional header along with PutObject and CompleteMultipartUpload API requests.

Amazon S3 now supports conditional writes - AWS

“can check for the existence of an object before creating it” なので、S3にオブジェクトを作成する前に存在確認ができます。使い方は”HTTP if-none-match conditional header along with PutObject and CompleteMultipartUpload API requests”ですが、これはsdkが引数として提供していたりします。なので、if-none-match headerを直接意識するケースは少ないと思います。

経緯3 Terraform state lockはS3だけでOKになった

ここでTerraform state lockの必要性を思い出すと、write操作が開始する時にstate lockをどこかに置いて、write操作が終了したらstate lockを削除する。そして他のwrite操作が来たらエラーが返る仕組みがあれば良いです。S3のConditional Writesはオブジェクト作成前に存在確認ができるので、これが使えます。

このPRで、Terraform state lockはS3のConditional Writesを使えるようになりました。 Introduce S3-native state locking by bschaatsbergen · Pull Request #35661 · hashicorp/terraform
リリースはv1.10.0 (2024/11/27)に含まれています。Changelog v1.10.0

現在(2026/02/16)どうなっているか

先ほどの PR#35661 では、将来のminor versionでDynamoDBを使ったstate lockがdeprecatedになることも記載されていました。
2026/02/16現在、Backend Type: s3 によると Enabling DynamoDB State Locking (Deprecated) と書いてありました。リリース v1.11.0 (2025/2/27)のChangelog v1.11.0 を見ると、S3のConditional WritesがGAになったタイミングでDynamoDBを使ったロック制御がdeprecatedになったようですね。

今は以下のようなコードで書けます。

terraform {
  backend "s3" {
    bucket  = "my-terraform-state"
    key     = "path/to/my/terraform.tfstate"
    region  = "ap-northeast-1"
    use_lockfile = true # dynamodb_table は不要になった
    encrypt = true
  }
}

まとめ

Conditonal Writesを使うので、Terraform backend S3はDynamoDBなしでstate lockができる。

Editing history

Changelog

  • Initial draft

Contact: uta8a.net/contact