From 96b7c02add8930c43f46347614ae5dd518a58683 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Jun 2026 01:56:22 +0000 Subject: [PATCH 1/2] docs(remote-backends): document S3-native state locking via useLockfile Document the new `useLockfile` field on the S3 backend, which enables S3-native state locking (lock file at .tflock) and removes the need for a separate DynamoDB table. Covers enabling it, required S3 permissions, and migrating from `dynamodbTable`, which is now deprecated. - concepts/remote-backends: new "State Locking with the S3 Backend" section with per-language examples and a migration guide - release/s3-native-locking (new page): What's New entry - release/index: What's New link to the new page - docs.json: nav entry for the new release page Documents open-constructs/cdk-terrain#254. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VzSEXFAfYFCKLQU2CHeCRN --- content/concepts/remote-backends.mdx | 148 ++++++++++++++++++++++++++ content/docs.json | 1 + content/release/index.mdx | 6 ++ content/release/s3-native-locking.mdx | 55 ++++++++++ 4 files changed, 210 insertions(+) create mode 100644 content/release/s3-native-locking.mdx diff --git a/content/concepts/remote-backends.mdx b/content/concepts/remote-backends.mdx index 63d36e3..9668647 100644 --- a/content/concepts/remote-backends.mdx +++ b/content/concepts/remote-backends.mdx @@ -407,6 +407,154 @@ In addition to HCP Terraform, Terraform and CDKTN support the following backends CDK Terrain v0.14 deprecated the artifactory, etcd, etcdv3, manta, and swift backends, and removed them in v0.20. Terraform removed these backends in v1.3. For migration paths from these removed backends, refer to [Upgrading to Terraform v1.3](https://developer.hashicorp.com/terraform/language/v1.3.x/upgrade-guides). +## State Locking with the S3 Backend + +When several people or automated pipelines run against the same state, Terraform (or OpenTofu) uses [state locking](https://developer.hashicorp.com/terraform/language/state/locking) to prevent concurrent runs from corrupting the state file. + +The S3 backend supports two locking mechanisms: + +- **S3-native locking** (recommended) via the `useLockfile` property. Terraform writes a lock file alongside your state object in the same bucket — at `.tflock` — and removes it when the operation completes. No additional infrastructure is required. S3-native locking is available in Terraform 1.10 and later and OpenTofu 1.10 and later. +- **DynamoDB locking** via the `dynamodbTable` property, which points the backend at a DynamoDB table whose partition key is `LockID`. This is the legacy mechanism and is now deprecated in favor of `useLockfile`. + +If you set neither property, state locking is disabled. + +### Enable S3-Native Locking + +Set `useLockfile` to `true` on the `S3Backend` configuration. + + + + +```ts TypeScript +import { Construct } from "constructs"; +import { S3Backend, TerraformStack } from "cdktn"; + +export class S3BackendStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new S3Backend(this, { + bucket: "my-terraform-state", + key: "my-app/terraform.tfstate", + region: "us-east-1", + encrypt: true, + useLockfile: true, + }); + } +} +``` + +```java Java +import software.constructs.Construct; +import io.cdktn.cdktn.TerraformStack; +import io.cdktn.cdktn.S3Backend; +import io.cdktn.cdktn.S3BackendConfig; + +public class MainS3Backend extends TerraformStack { + + public MainS3Backend(Construct scope, String id) { + super(scope, id); + + new S3Backend(this, S3BackendConfig.builder() + .bucket("my-terraform-state") + .key("my-app/terraform.tfstate") + .region("us-east-1") + .encrypt(true) + .useLockfile(true) + .build() + ); + } +} +``` + +```python Python +from constructs import Construct +from cdktn import S3Backend, TerraformStack + +class S3BackendStack(TerraformStack): + def __init__(self, scope: Construct, id: str): + super().__init__(scope, id) + + S3Backend(self, + bucket = "my-terraform-state", + key = "my-app/terraform.tfstate", + region = "us-east-1", + encrypt = True, + use_lockfile = True + ) +``` + +```csharp C# +using Constructs; +using Io.Cdktn; + +namespace Examples +{ + class S3BackendStack : TerraformStack + { + public S3BackendStack(Construct scope, string name) : base(scope, name) + { + new S3Backend(this, new S3BackendConfig + { + Bucket = "my-terraform-state", + Key = "my-app/terraform.tfstate", + Region = "us-east-1", + Encrypt = true, + UseLockfile = true + }); + } + } +} +``` + +```go Go +import ( + "github.com/aws/constructs-go/constructs/v10" + "github.com/aws/jsii-runtime-go" + "github.com/open-constructs/cdk-terrain-go/cdktn" +) + +func NewS3BackendStack(scope constructs.Construct, name string) cdktn.TerraformStack { + stack := cdktn.NewTerraformStack(scope, &name) + + cdktn.NewS3Backend(stack, &cdktn.S3BackendConfig{ + Bucket: jsii.String("my-terraform-state"), + Key: jsii.String("my-app/terraform.tfstate"), + Region: jsii.String("us-east-1"), + Encrypt: jsii.Bool(true), + UseLockfile: jsii.Bool(true), + }) + + return stack +} +``` + + + +The identity that runs `cdktn` operations needs `s3:GetObject`, `s3:PutObject`, and `s3:DeleteObject` permissions on the lock file path so Terraform can create and release the lock. + +### Migrate from DynamoDB to S3-Native Locking + +If you already lock state with a DynamoDB table, you can move to S3-native locking without a window where state is unprotected by enabling both mechanisms for a single run, then removing the DynamoDB table. + +1. Keep `dynamodbTable` and add `useLockfile: true` to your `S3Backend` configuration. With both set, Terraform acquires both locks. + + ```ts + new S3Backend(this, { + bucket: "my-terraform-state", + key: "my-app/terraform.tfstate", + region: "us-east-1", + dynamodbTable: "my-lock-table", + useLockfile: true, + }); + ``` + +2. Run `cdktn deploy` (or `cdktn diff`) once so the change takes effect and the backend is reconfigured. + +3. Remove `dynamodbTable`, leaving only `useLockfile: true`. After your next run no longer references the table, you can delete the DynamoDB table. + +`dynamodbTable` remains available for backwards compatibility, but it is deprecated. Terraform deprecated the `dynamodb_table` argument in the S3 backend starting with v1.11 and may remove DynamoDB-based locking in a future release. Prefer `useLockfile` for new projects. + ## Escape Hatches Escape hatches can add to or override existing resources, and you can use them for backends or backend constructs that CDKTN does not natively support. Escape hatch methods have an `Override` suffix (e.g., `addOverride`). diff --git a/content/docs.json b/content/docs.json index 2559479..41e3b37 100644 --- a/content/docs.json +++ b/content/docs.json @@ -99,6 +99,7 @@ "expanded": false, "pages": [ "release/index", + "release/s3-native-locking", "release/upgrade-guide-v0-23", "release/upgrade-guide-v0-22", "release/upgrade-guide-v0-19", diff --git a/content/release/index.mdx b/content/release/index.mdx index 2e32960..ab25354 100644 --- a/content/release/index.mdx +++ b/content/release/index.mdx @@ -6,6 +6,12 @@ description: >- We release CDK Terrain (CDKTN) regularly. The [CHANGELOG on Github](https://github.com/open-constructs/cdk-terrain/blob/main/CHANGELOG.md) contains details about bug fixes, new features, and deprecations. +## What's New + +- [S3-native state locking](/release/s3-native-locking) — the `S3Backend` can now + lock state with a native lock file via the `useLockfile` field, removing the + need for a separate DynamoDB table. + ## Upgrade Guides CDKTN includes upgrade guides for releases that have breaking changes. diff --git a/content/release/s3-native-locking.mdx b/content/release/s3-native-locking.mdx new file mode 100644 index 0000000..13c72ec --- /dev/null +++ b/content/release/s3-native-locking.mdx @@ -0,0 +1,55 @@ +--- +title: "What's New: S3-Native State Locking" +sidebarTitle: "S3-Native Locking" +description: >- + The S3 backend can now lock state with a native lock file via the useLockfile + field, removing the need for a separate DynamoDB table. +--- + +The `S3Backend` now supports [S3-native state locking](/concepts/remote-backends#state-locking-with-the-s3-backend) +through a new `useLockfile` field, so you no longer need a DynamoDB table to +lock Terraform state stored in S3. + +## What changed + +### New `useLockfile` field + +Set `useLockfile: true` on the `S3Backend` configuration to enable +S3-native locking. Terraform (or OpenTofu) writes a lock file next to your +state object — at `.tflock` — for the duration of each operation and +removes it when the operation finishes. No additional infrastructure is +required. + +```ts +new S3Backend(this, { + bucket: "my-terraform-state", + key: "my-app/terraform.tfstate", + region: "us-east-1", + encrypt: true, + useLockfile: true, +}); +``` + +S3-native locking is available in Terraform 1.10 and later and OpenTofu 1.10 +and later. The identity that runs `cdktn` operations needs `s3:GetObject`, +`s3:PutObject`, and `s3:DeleteObject` permissions on the lock file path. + +### `dynamodbTable` is deprecated + +The `dynamodbTable` field — which points the S3 backend at a DynamoDB table +for locking — is now deprecated in favor of `useLockfile`. It still works for +backwards compatibility, but Terraform deprecated the underlying +`dynamodb_table` argument starting with v1.11 and may remove DynamoDB-based +locking in a future release. + +## Migrating existing projects + +You can move from DynamoDB to S3-native locking without leaving state +unprotected by enabling both for a single run: + +1. Add `useLockfile: true` while keeping `dynamodbTable`. +2. Run `cdktn deploy` (or `cdktn diff`) once to reconfigure the backend. +3. Remove `dynamodbTable`, then delete the DynamoDB table. + +See [State Locking with the S3 Backend](/concepts/remote-backends#state-locking-with-the-s3-backend) +for full documentation and per-language examples. From 02c735507e4a82e7b34920e29539dfea3fb9965c Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Jun 2026 02:09:46 +0000 Subject: [PATCH 2/2] docs: call out declaring targetVersions for S3-native locking S3-native locking requires Terraform/OpenTofu 1.10+, which is newer than the default target ranges. Add callouts directing users to declare `targetVersions` in cdktf.json so synthesis validates native locking against the runtimes they target, mirroring the function-usage synth-time validation. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VzSEXFAfYFCKLQU2CHeCRN --- content/concepts/remote-backends.mdx | 20 ++++++++++++++++++++ content/release/s3-native-locking.mdx | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/content/concepts/remote-backends.mdx b/content/concepts/remote-backends.mdx index 9668647..61a5b89 100644 --- a/content/concepts/remote-backends.mdx +++ b/content/concepts/remote-backends.mdx @@ -533,6 +533,26 @@ func NewS3BackendStack(scope constructs.Construct, name string) cdktn.TerraformS The identity that runs `cdktn` operations needs `s3:GetObject`, `s3:PutObject`, and `s3:DeleteObject` permissions on the lock file path so Terraform can create and release the lock. + + S3-native locking requires Terraform 1.10 or OpenTofu 1.10 (or later). + Declare the runtime versions your project supports in the + [`targetVersions`](/create-and-deploy/configuration-file#declare-target-runtimes) + field of `cdktf.json` so that synthesis validates native locking against the + versions you target — the default targets (`terraform >=1.5.7`, + `opentofu >=1.6.0`) predate it. This is the same declarative, + binary-free check CDK Terrain applies to + [function usage at synth time](/concepts/functions#validating-function-usage-at-synth-time). + + ```json + { + "targetVersions": { + "terraform": ">=1.10.0", + "opentofu": ">=1.10.0" + } + } + ``` + + ### Migrate from DynamoDB to S3-Native Locking If you already lock state with a DynamoDB table, you can move to S3-native locking without a window where state is unprotected by enabling both mechanisms for a single run, then removing the DynamoDB table. diff --git a/content/release/s3-native-locking.mdx b/content/release/s3-native-locking.mdx index 13c72ec..719840d 100644 --- a/content/release/s3-native-locking.mdx +++ b/content/release/s3-native-locking.mdx @@ -34,6 +34,14 @@ S3-native locking is available in Terraform 1.10 and later and OpenTofu 1.10 and later. The identity that runs `cdktn` operations needs `s3:GetObject`, `s3:PutObject`, and `s3:DeleteObject` permissions on the lock file path. + + Declare the runtime versions your project supports in the + [`targetVersions`](/create-and-deploy/configuration-file#declare-target-runtimes) + field of `cdktf.json` so that synthesis validates native locking against the + versions you target. The default targets predate `useLockfile`, so raise the + floor to `">=1.10.0"` for each product you support. + + ### `dynamodbTable` is deprecated The `dynamodbTable` field — which points the S3 backend at a DynamoDB table