---
title: "AWS CDKのスタックとは？CloudFormationとの対応・分割とcdk deployの手順"
url: "https://www.issoh.co.jp/column/details/2892/"
published: 2024-07-02
updated: 2026-10-13
categories: ["プラットフォーム"]
publisher: "株式会社一創"
---

# AWS CDKのスタックとは？CloudFormationとの対応・分割とcdk deployの手順

AWS CDKを書き始めて最初につまずくのが、スタックという単位の扱いです。ファイルを分けたつもりがスタックまで分かれてしまう、別スタックのリソースを参照したらデプロイが通らなくなる、`cdk deploy` にワイルドカードを渡したのに一部しか反映されない。いずれもスタックがCloudFormation側で何に対応しているかを押さえていないことが原因です。この記事では、[AWS CDK v2開発者ガイドのスタックの章](https://docs.aws.amazon.com/cdk/v2/guide/stacks.html)とCloudFormationのクォータ表をもとに、最初のスタックを作ってデプロイする手順から、スタックの定義、分割の判断基準、デプロイ時の対象指定、採用を見送る場面までを2026年10月時点の情報で整理します。CDKそのものの仕組みや、CloudFormation・Terraformとの位置づけの違いは[AWS CDK（cdk）とは？仕組み・使い方とCloudFormation・Terraformとの違い](https://www.issoh.co.jp/tech/details/3161/)で扱っているため、ここではスタックに絞ります。

## まとめ：AWS CDKのスタック設計とデプロイの要点（2026年10月時点）

- CDKのスタックはデプロイの最小単位で、1つのCDKスタックがそのまま1つのCloudFormationスタックとしてデプロイされます。
- 最初の1スタックは `cdk init` で雛形を作り、`cdk bootstrap`・`cdk synth`・`cdk diff`・`cdk deploy` の順で出します。
- スタックの物理名はコンストラクトツリー上のパスから自動生成されます。名前を固定したいときだけ `stackName` で明示します。
- ファイルを分けたいだけならスタックを分ける必要はありません。コンストラクトに切り出せば1スタックのまま複数ファイルに分割できます。
- スタックをまたいでリソースを渡すと、CDKがExportとFn::ImportValueを自動生成します。この参照を後から外すとデプロイ順序によっては失敗するため、`exportValue` を使った3段階の手順が要ります。
- 1テンプレートあたりのリソースは500が上限です。超える場合はNestedStackで逃がせますが、`cdk list` に出ず単独デプロイもできません。
- AWSに閉じた構成をTypeScriptなどで書けるチームなら採用、マルチクラウドや既存のTerraform資産がある現場では見送りが妥当です。

根拠と具体的な書き方は、以降の章で手を動かす順に並べています。

## AWS CDKで最初のスタックを作る手順：インストールからcdk deployまで

スタックの理屈に入る前に、1つのスタックを実際にデプロイするまでの最短経路を示します。手順は[公式の「Getting started with the AWS CDK」](https://docs.aws.amazon.com/cdk/v2/guide/getting-started.html)と[チュートリアル「Create your first AWS CDK app」](https://docs.aws.amazon.com/cdk/v2/guide/hello-world.html)に沿っています。

### npm install -g aws-cdkとcdk initでのスタック雛形の生成手順

CDK CLIはnpmパッケージ `aws-cdk` として配布されています。2026年10月13日時点のnpm registryでは最新が2.1145.0系で、実行に必要なNode.jsのバージョンは18以上です。プロジェクトに入るライブラリ `aws-cdk-lib` は2.273.0系でNode.js 20以上が条件なので、手元はNode.js 20以上にそろえておきます。ソースは[GitHubのaws/aws-cdkリポジトリ](https://github.com/aws/aws-cdk)で公開されています。

```
$ npm install -g aws-cdk
$ cdk --version
$ mkdir hello-cdk && cd hello-cdk
$ cdk init app --language typescript
```

`cdk init` はディレクトリ名からクラス名を決めます。`hello-cdk` で実行すると、`lib/hello-cdk-stack.ts` に `HelloCdkStack` というスタッククラス、`bin/hello-cdk.ts` にそれをAppへ登録するコードが生成されます。この2ファイルの分担は、後の章で扱うスタック定義の基本形そのものです。

生成されたスタッククラスにS3バケットを1つ足すと、デプロイして確かめられる最小構成になります。検証用なので、削除時にバケットごと消える設定を入れています。

```
// lib/hello-cdk-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';

export class HelloCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });
  }
}
```

### cdk bootstrap・synth・diff・deployの順に1スタックを出す流れ

雛形ができたら、次の4コマンドを順に通します。アカウントIDとリージョンは自分の環境に置き換えてください。

```
$ cdk bootstrap aws://123456789012/ap-northeast-1
$ cdk synth
$ cdk diff
$ cdk deploy HelloCdkStack
```

1. `cdk bootstrap`：デプロイ先の環境に、アセット置き場のS3バケットやデプロイ用IAMロールを作ります。アカウントとリージョンの組ごとに1回です（[公式のブートストラップ解説](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html)）。
2. `cdk synth`：TypeScriptのコードを実行し、`cdk.out` にCloudFormationテンプレートを出力します。ここで出たテンプレートが、スタック1つにつき1枚です。
3. `cdk diff`：公式チュートリアルの出力例どおり、読み取り専用の変更セットを作って、デプロイ済みの状態との差分を表示します。
4. `cdk deploy`：変更セットを作って適用し、CloudFormationスタック `HelloCdkStack` が作成されます。

デプロイ後にCloudFormationのコンソールを開くと、`HelloCdkStack` という名前のスタックが並んでいるはずです。CDKで書いたスタックとコンソール上のスタックが同じものだという点が、次章以降のすべての前提になります。不要になったら `cdk destroy HelloCdkStack` で削除します。

## CDKスタックとCloudFormationスタックの1対1対応と合成の仕組み

### デプロイの最小単位としての1スタック1テンプレートとコンソール上の実体

AWS CDK v2開発者ガイドは、スタックを「デプロイの単一かつ最小の単位（the smallest single unit of deployment）」と定義しています。CDKアプリをデプロイすると、1つのCDKスタックに含まれるリソースはまとめて1つのCloudFormationスタックとして展開されます。つまりCDK側のスタックとCloudFormation側のスタックは1対1です。

この対応関係が、後述する制限のほとんどを説明します。CloudFormationのテンプレートに500リソースまでという上限があるのは、CDKで1つのスタックに詰め込めるリソースの上限がそのまま500だという意味になります。マネジメントコンソールのCloudFormation画面に並ぶスタックは、CDKで定義したスタックの実体そのものです。CloudFormation側のテンプレート構造やスタック操作については、[AWS CloudFormationとは？テンプレートの書き方・スタック操作と更新で消える設定の防ぎ方](https://www.issoh.co.jp/tech/details/2927/)で扱っています。

### App・Stack・Constructの階層とcdk synthによるテンプレート出力数

CDKアプリは、最上位のApp、その下のStack、さらに下のConstructという入れ子で構成されます。リソースを表すのはConstructで、Stackはそれを束ねる器です。`cdk synth` を実行すると、アプリ内のスタックごとに別々のテンプレートを含むクラウドアセンブリが生成されます。

ここで注意したいのは、同じクラスから作った2つのスタックであってもCDKは2枚の独立したテンプレートとして出力する点です。CloudFormationの一般的な使い方では、1枚のテンプレートをパラメータで切り替えて複数回デプロイします。CDKは合成時点で具体的な値を解決する設計のため、公式ドキュメントもCloudFormationパラメータの利用を推奨していません。パラメータはデプロイ時にしか解決されず、コード側でその値を判定できないからです。環境ごとの差分は、パラメータではなくTypeScriptの `if` 文で分岐させます。

同じテンプレートを複数アカウント・複数リージョンへ一括展開したい要件なら、CDKのマルチスタックではなくCloudFormation側の仕組みが候補になります。権限モデルと更新時の注意は[CloudFormation StackSetsの権限モデル・デプロイオプションと更新の落とし穴](https://www.issoh.co.jp/tech/details/8400/)で整理しています。

## Stackクラスを継承してスタックを定義しAppへ登録する手順と命名・環境指定

### lib配下のスタックファイルとbin配下のアプリケーションファイルの分担

スタックは `Stack` クラスを継承して定義します。公式ドキュメントが示す一般的なパターンは、スタックの定義をスタックファイルに置き、Appの生成とスタックのインスタンス化をアプリケーションファイルに分ける構成です。`cdk init` が生成する `lib` と `bin` の分担もこれに従っています。

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class MyCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    // ここにコンストラクトを定義する
  }
}
```

定義しただけではスタックは作られません。Appのコンテキストでインスタンス化して初めてデプロイ対象になります。

```
// bin/my-app.ts
import * as cdk from 'aws-cdk-lib';
import { MyCdkStack } from '../lib/my-cdk-stack';
const app = new cdk.App();
new MyCdkStack(app, 'MyCdkStack', {});
```

同じAppに複数のスタックを登録すれば、そのままマルチスタック構成になります。`new MyFirstStack(app, 'stack1')` と `new MySecondStack(app, 'stack2')` のように並べるだけです。

### スタック名の自動生成規則とstackNameでの明示指定・128文字上限

CloudFormationスタックの物理名は、コンストラクトツリー上のスタックのパスからCDKが自動的に決めます。既定の名前を導出する際の基になるのは、StackオブジェクトのコンストラクトIDです。公式ドキュメントが載せる `cdk ls` の出力例では、beta環境とprod環境それぞれに3スタックを持つアプリが `betacpDA8372D3` や `prodmon631A1083` のように、パスの連結にハッシュが付いた名前になっています。

命名規則を組織で決めている場合や、既存のCloudFormationスタック名に合わせたい場合は `stackName` プロパティで上書きします。コンストラクトIDと物理名は独立しているため、次のような指定も成立します（親コンストラクトの中でスタックを生成する場合の例です）。

```
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
```

スタック名の上限は128文字です。自動生成に任せると環境名やパスの連結で長くなりやすいので、階層の深いパイプライン構成では明示指定に倒したほうが安全です。

### envでアカウントとリージョンを固定する書き方と、省略時に生じる2つの制約

スタックはAWSアカウントとリージョンの組み合わせ、すなわち環境に対してデプロイされます。`env` を省略したスタックは環境非依存（environment-agnostic）となり、アカウントとリージョンがCloudFormationの擬似パラメータに解決されます。

```
const envUSA = { account: '837873873873', region: 'us-west-2' };
new MyFirstStack(app, 'first-stack-us', { env: envUSA });
// 資格情報ファイルの値を使う場合
new MyDevStack(app, 'dev', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION
  }
});
```

環境非依存にしておけばどこにでもデプロイできる、と考えると2か所で詰まります。1つ目は `stack.availabilityZones` です。環境非依存スタックでは実際のリージョンを問い合わせられないため、公式ドキュメントの記述どおり常に2つのアベイラビリティゾーンを含む配列が返ります。3AZ以上を前提にした構成を組んでいると、意図せず2AZに縮んだテンプレートが出力されます。

2つ目は既存リソースの参照です。`Vpc.fromLookup()` は合成時にアカウントへ問い合わせて対象を特定する仕組みのため、環境非依存スタックでは動作しません。どの環境を照会すればよいかCDK Toolkitが判断できないからです。既存VPCを引き当てる構成なら、`env` にアカウントとリージョンを明示するのが前提条件になります。

## 複数スタックへ分割する判断基準とクロススタック参照を外すときの落とし穴

### スタック分割とファイル分割の切り分け：ライフサイクルの違いで判断する基準

ソースが肥大化してきたからスタックを分ける、という判断は目的と手段がずれています。CDKではコンストラクトという抽象化の単位が用意されているため、1つのスタックのままリソース定義を複数ファイルへ切り出せるからです。ファイルの分割はスタックの分割に依存しません。

スタックを分ける理由になるのは、ライフサイクルが違うときです。VPCやRoute 53のホストゾーンのように一度作ったらほとんど変更しないリソースと、日に何度も入れ替わるLambda関数やECSサービスを同じスタックに置くと、更新のたびに前者まで変更セットの評価対象になります。逆に、同時に作られ同時に捨てられるリソースを別スタックへ切り出すのは、後述するクロススタック参照の面倒を持ち込むだけで得るものがありません。チーム分割やレビュー単位を理由にした分割も、まずコンストラクトへの切り出しで足ります。

### スタック間のバケット受け渡しで自動生成するExportとFn::ImportValue

別スタックのリソースを参照するときは、生成側スタックがリソースへの参照を属性として保持し、消費側スタックのコンストラクタへ渡します。同じアプリ内かつ同じ環境であることが条件です（[公式「Resources and the AWS CDK」](https://docs.aws.amazon.com/cdk/v2/guide/resources.html)）。

```
const prod = { account: '123456789012', region: 'us-east-1' };
const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod });
const stack2 = new StackThatExpectsABucket(app, 'Stack2', {
  bucket: stack1.bucket,
  env: prod
});
```

リソースが同じ環境の別スタックにあるとCDKが判断すると、生成側にCloudFormationのExportを、消費側にFn::ImportValueを自動的に合成して値を受け渡します。開発者がOutputsを手で書く必要はありません。同時に、2つのスタックのあいだにデプロイ順序の依存関係が生まれます。

### 参照を外したときのデプロイ失敗とexportValueを使う3段階の解消手順

この自動化が牙をむくのが、共有をやめるときです。公式ドキュメントは、消費側から共有リソースの利用を削除すると予期しないデプロイ失敗を引き起こしうると説明しています。起きるのは、2つのスタックに別の依存関係があって同じ順序でのデプロイが強制される場合、あるいは依存が無くてもCDK Toolkitがたまたま生成側を先にデプロイする場合です。このとき生成側では不要になったExportが消える一方、消費側の更新はまだ反映されていません。使用中のExportを削除しようとして生成側のデプロイが失敗します。

公式ドキュメントが示す解消手順は3段階です。`Stack` クラスの `exportValue` メソッドが、この手動Exportを作るために用意されています。

1. 生成側スタックに、自動生成されていたものとまったく同じ論理IDでExportを手動追加する（`exportValue` を使う）。
2. 消費側スタックから共有リソースの利用を削除し、両方のスタックをデプロイする。
3. 手動で追加したExportを外し、再度両方のスタックをデプロイする。

```
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';
export class StackThatProvidesABucket extends cdk.Stack {
  public readonly bucket: s3.IBucket;
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    this.bucket = new s3.Bucket(this, 'SharedBucket');
    // 参照を外す前に、同じ論理IDのExportを一時的に固定する
    this.exportValue(this.bucket.bucketArn);
  }
}
```

この手順を知らないまま本番環境で参照を外すと、デプロイ順序が悪かった場合に生成側のスタックが更新できない状態で止まります。クロススタック参照は自動化の恩恵が大きい反面、後戻りのコストが高い機能だと理解したうえで使ってください。

## 1スタック500リソースの上限とNestedStackで逃がすときの運用上の制約

### スタック設計に効くCloudFormationクォータ8項目と51,200バイトの壁

スタックの設計に効いてくるCloudFormation側のクォータは次のとおりです。値は2026年10月13日に[CloudFormationユーザーガイドのクォータ一覧](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html)で確認しました。CDKで書いていても、合成後のテンプレートがこの制限を受けます。

| 項目                     | 上限        |
| ---------------------- | --------- |
| テンプレート内のリソース数          | 500       |
| 作成できるスタック数             | 2,000     |
| テンプレート内のOutputs        | 200       |
| テンプレート内のParameters     | 200       |
| スタック名の長さ               | 128文字     |
| リクエストで渡すテンプレート本文       | 51,200バイト |
| S3オブジェクト経由のテンプレート本文    | 1MB       |
| ネストされたスタックの1操作あたりリソース数 | 2,500     |

未ブートストラップの環境で最初に当たるのが51,200バイトの壁です。CDK CLIのドキュメントは、環境がブートストラップされていない場合、アセットを持たず、かつ合成後のテンプレートが51,200バイト未満のスタックだけがデプロイに成功すると明記しています。`cdk bootstrap` を済ませればテンプレートはS3経由で渡せるようになり、上の表にあるCloudFormation側の上限である1MBまで伸ばせます。ただしリソース500の上限はブートストラップの有無と無関係に効いたままです。

ブートストラップで作られるロールの内訳と、テンプレート版番号の確認方法は[cdk bootstrapが作る5つのIAMロールとテンプレート版32の更新手順](https://www.issoh.co.jp/tech/details/17614/)にまとめています。

### NestedStackで回避できる範囲と、cdk listに出ない制約

500リソースを超える場合の逃げ道が [NestedStack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html) です。ネストされたスタックは親スタックの中で1リソース分としてカウントされ、その内部にさらに500リソースまで持てます。ただし上の表のとおり、階層全体で1回のデプロイが作成・更新・削除できるのは2,500リソースまでです。

```
import { NestedStack, NestedStackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class MyNestedStack extends NestedStack {
  constructor(scope: Construct, id: string, props?: NestedStackProps) {
    super(scope, id, props);
    // 通常のスタックと同じようにコンストラクトを定義できる
  }
}
```

ただし独立したデプロイ成果物としては扱われません。ネストされたスタックは `cdk list` の一覧に出ず、`cdk deploy` での単独デプロイも対象外になります。運用面でより重いのは差分表示の制約です。デプロイ前のセキュリティ体制の変更点は、公式ドキュメントいわくトップレベルのスタックについてしか表示されません。IAMロールやセキュリティグループの権限拡大がネスト内で起きても、承認プロンプトの材料として出てこないということです。`cdk deploy --parameters` で渡した値もネストされたスタックには伝播しない点に注意が要ります。

したがって、単に構成を整理したいという理由でNestedStackを選ぶべきではありません。リソース数が500に迫っている、あるいはテンプレートサイズが上限に近い、という明確な理由があるときに限って使う機能です。整理が目的ならコンストラクトへの切り出しを選びます。

## cdk deployでのスタック指定とexclusively・承認・ロールバックの制御

### スタック名指定と–all・ワイルドカード・–exclusivelyでの対象選択

デプロイ対象はスタックのコンストラクトIDで指定します。まず `cdk list` で名前を確認し、必要なものだけを渡すのが基本です。オプションの一覧は[CDK CLIリファレンスの cdk deploy](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-deploy.html)にあります。

```
$ cdk list
CdkHelloWorldStack
CdkStack2
CdkStack3
$ cdk deploy CdkHelloWorldStack CdkStack3
$ cdk deploy --all
```

パイプラインのようにスタックが階層構造になっている場合、ここに落とし穴があります。`--all` とワイルドカードの `*` は最上位のスタックにしかマッチしません。階層下のすべてのスタックを対象にするには `**` を使います。

```
$ cdk deploy PipelineStack/Prod/**
```

スタック名を指定すると、依存関係にあるスタックも一緒にデプロイされます。要求したスタックだけを対象にしたいときは `--exclusively`（短縮形 `-e`）を付けます。リファレンスの説明は「要求したスタックだけをデプロイし、依存先を含めない」です。依存先スタック側の変更はこのとき反映されないので、依存先が最新の状態でデプロイ済みだと分かっていて、消費側だけを素早く更新したい場面に限ります。複数スタックを並行してデプロイする `--concurrency` は既定値が1で、明示的に数を渡さないかぎり直列実行のままです。

```
$ cdk deploy Stack2 --exclusively
$ cdk deploy --all --concurrency 3
```

### 変更セット方式cdk-deploy-change-setと承認・ロールバックの既定値

CDK CLIの既定のデプロイ方式は変更セットです（`--method` の既定値が `change-set`）。このとき作られる変更セットの名前は既定で `cdk-deploy-change-set` になります。この既定名の挙動が公式ドキュメントに詳しく書かれているのは `--method='prepare-change-set'` の説明で、同名の変更セットが既に存在すれば上書きされ、差分が検出されなくても空の変更セットが作られる、とされています。デプロイ時にこの名前を含むエラーが出る場合は、CDKが毎回この固定名を使う仕様が背景にあると押さえておくことが、エラーの原因を早く切り分けるための手掛かりです。変更セットを作らず即時に適用する `--method='direct'` も選べますが、CLI出力の進捗詳細は失われます。

承認の既定値は `--require-approval broadening` で、権限やセキュリティグループの範囲が広がる変更のときだけ手動承認を求めます。CI上で止まらないようにするには `never` を指定しますが、これはセキュリティ関連の変更を無確認で通す設定です。ロールバックは既定で有効で、リソースの作成や更新に失敗すると直前の安定状態まで巻き戻ります。開発中に反復を速めたい場合は `--no-rollback` で失敗状態を保持できますが、リソースの置き換えを伴うデプロイは必ず失敗します。

### cdk destroy実行時のRemovalPolicy既定値RETAINとリソース残存

`cdk destroy MyCdkStack` でスタックを削除してもデータが消えない、という挙動はCDK固有の設計です。S3バケットやDynamoDBテーブルのように永続データを持つリソースには削除ポリシーがあり、CDKの `RemovalPolicy` は既定が `RETAIN` です。CloudFormationのDeletionPolicyの既定とは逆向きになっています。

```
const bucket = new s3.Bucket(this, 'Bucket', {
  removalPolicy: cdk.RemovalPolicy.DESTROY,
  autoDeleteObjects: true
});
```

`RETAIN` のまま `cdk destroy` を実行すると、リソースはスタックから切り離されてアカウントに残ります。同じ名前で再デプロイしようとすると名前の衝突でエラーになるため、検証用スタックを作り直すたびに手作業の削除が発生します。開発環境では `DESTROY` を明示するのが実用的です。なお、中身の入ったS3バケットは `DESTROY` を指定してもCloudFormationが削除できません。`autoDeleteObjects: true` を併記して、破棄前にオブジェクトを消させる必要があります。

## AWS CDKとAWS SDKの役割の違いと実行タイミング・Node.js要件の整理

### 合成時とランタイムという実行タイミングの差と動作する場所の比較

名前が似ているため混同されがちですが、両者は動くタイミングが違います。CDKはデプロイ前にCloudFormationテンプレートを合成するツールで、SDKはアプリケーションの実行中にAWSサービスのAPIを呼ぶライブラリです。

| 観点      | AWS CDK              | AWS SDK               |
| ------- | -------------------- | --------------------- |
| 目的      | インフラの定義              | サービスAPIの呼び出し          |
| 動作タイミング | 合成・デプロイ時             | アプリ実行時                |
| 生成物     | CloudFormationテンプレート | APIリクエスト              |
| 代表パッケージ | aws-cdk-lib          | @aws-sdk/client-s3 ほか |

コードが動く場所も違います。CDKのコードは手元やCIサーバーで実行され、SDKのコードはLambdaやEC2の上で実行されます。

### CDKで定義しSDKから呼ぶ分担と、必要なNode.jsのバージョン

実際のシステムでは両方を使います。CDKでLambda関数とS3バケットを定義してデプロイし、そのLambdaのコードの中でSDKを使ってバケットへオブジェクトを書き込む、という分担です。SDK側の詳細は[AWS SDK for JavaScript v3の使い方とS3・DynamoDBの実装例](https://www.issoh.co.jp/tech/details/6814/)で解説しています。

実行環境の要件はCDKのCLIとライブラリで異なります。2026年10月13日時点のnpm registryの値では、CDK CLIの `aws-cdk` は2.1145.0でNode.js 18以上、ライブラリの `aws-cdk-lib` は2.273.0でNode.js 20以上を要求します（いずれも2026年10月8日公開）。両方を入れるCDKプロジェクトでは厳しいほうが効くため、実質的な下限はNode.js 20です。Node.js 18のままプロジェクトを作ると、ライブラリのインストール時に対応バージョン不一致の警告に当たります。

## AWS CDKを採用する条件と見送る場面：Terraform・SAMとの比較で判断

### CDKが向く条件：TypeScriptで書けてAWS単一クラウドに閉じる構成

CDKを選んでよいのは、次の2つがそろうときです。インフラがAWSに閉じていること、そしてアプリと同じTypeScriptやPythonでインフラを書けるメンバーがいることです。この条件なら、`if` 文やループで環境差分を書ける利点と、L2コンストラクトが権限やログ設定の既定値を埋めてくれる利点がそのまま効きます。スタックの分け方とクロススタック参照の扱いを本記事の基準で決めておけば、規模が大きくなっても破綻しにくい構成です。

IaCを導入するかどうか自体を検討している段階なら、先に[IaC（Infrastructure as Code）の仕組みと導入判断](https://www.issoh.co.jp/column/details/13004/)で、手作業の構築と比べた費用対効果を確認しておくと判断がぶれません。AWS上の構成設計からCDKやTerraformでのコード化までを外部に任せたい場合は、一創の[AWSを含むインフラ構築の支援](https://www.issoh.co.jp/service/system/aws/)で、既存環境の棚卸しから相談を受けています。

### CDKを見送る場面：マルチクラウド・既存Terraform資産・小規模サーバーレス

見送るべき場面ははっきりしています。Google CloudやAzureも同じコードで管理したい、あるいは既にTerraformのstateとモジュールが社内に積み上がっているなら、CDKを足すと管理ツールが2系統に割れるだけです。CDKの書き味でTerraformを動かすCDK for Terraformは提供終了しているため、その道もありません。経緯と移行先は[CDK for Terraform（CDKTF）の提供終了後の移行判断](https://www.issoh.co.jp/tech/details/16553/)で整理しています。

Lambda関数とAPI Gatewayが数本だけの小規模サーバーレスなら、CDKは過剰です。テンプレートとローカル実行環境がセットになった[AWS SAMのテンプレートとCLIの使い方](https://www.issoh.co.jp/tech/details/3823/)のほうが学習量が少なく済みます。より上位の部品を組み合わせるだけでよい場合は、[AWS BlocksとCDKの違いと採用判断](https://www.issoh.co.jp/tech/details/12663/)も比較対象に入ります。この3つの見送り条件のどれにも当たらないときに限ってCDKを選ぶ、と決めておくのが安全です。

## AWS CDKのスタックとcdk deployに関するよくある質問5問

AWS CDKのスタックについて、検索で多い疑問に短く答えます。

### CDKのスタックとCloudFormationのスタックは別物ですか？

同じものです。CDKのスタックはデプロイの最小単位で、その中のリソースは1つのCloudFormationスタックとしてまとめて展開されます。マネジメントコンソールのCloudFormation画面に表示されるスタックが、CDKで定義したスタックの実体です。したがってテンプレート1枚あたり500リソースというCloudFormationの上限は、CDKのスタックにもそのまま適用されます。

### スタックは1つにまとめるべきですか、分けるべきですか？

更新頻度が違うリソースが混在しているなら分けます。VPCやホストゾーンのような長寿命のリソースと、頻繁に入れ替わるLambdaやECSサービスを同居させると、毎回のデプロイで前者まで評価対象になります。逆に、コードの見通しを良くしたいだけならスタックを分ける必要はありません。CDKではコンストラクトに切り出すことで、1スタックのまま複数ファイルへ分割できます。

### cdk deployで作られる変更セットの名前は変えられますか？

変更セット名の既定値は `cdk-deploy-change-set` で、`--change-set-name` オプションで任意の名前を指定できます。公式ドキュメントの `--method='prepare-change-set'` の説明では、同名の変更セットが既に存在する場合は上書きされ、差分が検出されなくても空の変更セットが作成されるとされています。なお `--change-set-name` は `--method='direct'` とは併用できません。変更セットを作らずに即時適用する方式では、そもそも変更セットが生成されないためです。

### AWS CDKのバージョンはどう確認しますか？

CLIのバージョンは `cdk --version` で確認できます。ライブラリ側はプロジェクトの package.json に記載された aws-cdk-lib のバージョンを見ます。CDK v2ではライブラリが aws-cdk-lib に一本化されており、CLIとライブラリはバージョン番号の体系が別です。2026年10月13日時点の最新は aws-cdk-lib が2.273.0、CLIの aws-cdk が2.1145.0です。動作要件も別で、CLIはNode.js 18以上、aws-cdk-lib 2.273.0はNode.js 20以上を要求するため、プロジェクト全体ではNode.js 20以上を用意してください。

### スタックを削除するとリソースも消えますか？

永続データを持つリソースは既定で残ります。CDKの `RemovalPolicy` の既定値は `RETAIN` で、CloudFormationのDeletionPolicyの既定とは逆です。S3バケットやDynamoDBテーブルは `cdk destroy` の後もスタックから切り離されてアカウントに残るため、同名で再デプロイすると衝突します。検証環境では `removalPolicy: RemovalPolicy.DESTROY` を明示し、中身のあるS3バケットには `autoDeleteObjects: true` を併せて指定してください。

## 関連記事

- [AWS CDK（cdk）とは？仕組み・使い方とCloudFormation・Terraformとの違い](https://www.issoh.co.jp/tech/details/3161/)：CDK全体の仕組みと他ツールとの位置づけ
- [AWS CloudFormationとは？テンプレートの書き方・スタック操作と更新で消える設定の防ぎ方](https://www.issoh.co.jp/tech/details/2927/)：CDKが出力するテンプレートの読み方
- [cdk bootstrapが作る5つのIAMロールとテンプレート版32の更新手順](https://www.issoh.co.jp/tech/details/17614/)：デプロイ前提となるブートストラップの中身
- [AWS CloudFormation Expressモードとは？最大4倍高速化の仕組み・制約と本番適用の判断を実装者目線で解説](https://www.issoh.co.jp/tech/details/16395/)：スタック更新の待ち時間を縮める選択肢
- [AWS SDK for JavaScript v3の使い方｜v2からの移行手順とS3・DynamoDBの実装例](https://www.issoh.co.jp/tech/details/6814/)：CDKで作ったリソースをアプリから呼ぶ側

---

出典: [AWS CDKのスタックとは？CloudFormationとの対応・分割とcdk deployの手順](<https://www.issoh.co.jp/column/details/2892/>)（株式会社一創）
