AWS CDK で新たに、今後の CDK の肝となる Mixins という機能が Developer Preview として導入されました。
この機能により今後の CDK の使い方が大きく変わるであろう一大機能です。
目次
本記事の利用 CDK バージョン (2026/02/13 追記)
本記事で使用する CDK バージョンは以下の通りです。
- CDK: aws-cdk-lib: 2.238.0
- Mixins モジュール: @aws-cdk/mixins-preview: 2.238.0-alpha.0
- CDK CLI: aws-cdk: 2.1106.0
本記事の公開時は Mixins がリリースされた v2.229.0 を使用していましたが、その後いくつか破壊的変更が発生したため、v2.238.0 にバージョンを上げて本記事のサンプルコードも修正しています。また、新たな機能も追加されていたため、それらも追記しています。
Mixins とは (2026/03/03 追記)
2025 年 11 月現在、Mixins は Developer Preview です。今後、仕様や挙動が大きく変更される可能性があるので、使用の際には十分に注意してください。
追記: 2026 年 3 月、CDK v2.241.0 で、Mixins のコア機能がステーブルパッケージ(aws-cdk-lib)に移行され GA されました!
残りの機能(コア機能以外の各 Mixin クラスなど)に関しては、引き続きプレビューパッケージで開発が続きます。
Mixins の概要
Mixins は、L1 や L2 Construct などのレベルを問わず、任意の Construct に組合せ可能な抽象化を適用するための仕組みです。
CDK v2.229.0 で導入されましたが、2025 年 11 月現在 Developer Preview です。まだ全ての機能が揃っているわけではなく、今後も機能追加や改善が行われる予定です。
本記事は、Mixins の README や RFC などの内容をもとに、よりわかりやすく Mixins の概要や使い方を解説します。
- README
- RFC
- 2025 年 11 月 25 日時点、まだ RFC はまだマージされていないため、上記 PR リンクを掲載しています。
- 他にも機能が追加される予定なので、まだマージはされなさそうです。
Mixins の特徴
Mixins によって、従来は L2 Construct で行われていた抽象化を L1 Construct やカスタムコンストラクトに部分的に適用できるようにすることで、L2 Construct を使わずともユーザが必要な機能のみを導入できるようになります。
これにより、L2 Construct の一部の抽象化は魅力的だが適用したくない抽象化もあるといった場合でも、必要な機能のみを選択的に導入できるようになります。
また、各 AWS サービスに新機能が追加された場合、L1 Construct にはすぐに新しいプロパティが反映されますが、L2 Construct には反映されるまでに時間がかかります。Mixins を使用することで、L2 Construct にそのプロパティが追加される前でも、ユーザ側で L2 Construct に(エスケープハッチを使わずとも)簡単かつ安全に新しいプロパティを反映できるようにもなります。
つまり、Mixins によって、L1 / L2 Construct 間の隔たりが少なくなり、より柔軟なコンストラクトの設計が可能になります。
さらに Mixins では、様々な AWS サービス間で抽象的に暗号化などの共通パターンを適用できる仕組みも提供されます。
インストール
Mixins はまだ Developer Preview であるため、@aws-cdk/mixins-preview パッケージとして提供されています。
npm install -D @aws-cdk/mixins-preview
注意
既存の CDK プロジェクト(TypeScript)で Mixins を導入して cdk deploy や cdk synth などでエラーが出る場合、まず tsconfig.json を確認してみてください。
CDK CLI の新しいバージョン(2.1033.0)では以下の設定で生成されますが、もし該当プロジェクトの設定が異なる場合は合わせることで解決する可能性があります。
{ "compilerOptions": { "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", "lib": [ "es2022" ], ..., ..., "skipLibCheck": true, }
Mixins の使い方
Mixins は、Mixins.of() メソッドや各コンストラクトのwith()メソッドを用いて適用します。
with() メソッドは、使用するファイルで @aws-cdk/mixins-preview/with モジュールの import を記述することで利用可能になります(import '@aws-cdk/mixins-preview/with')。
※.with() メソッドは、現在は JavaScript と TypeScript でのみ利用可能です。import が必要なのはプレビュー期間中のみです。API が安定すると、.with() メソッドはすべてのコンストラクトで、すべての言語でデフォルトで使用できるようになります。
import * as cdk from 'aws-cdk-lib'; import '@aws-cdk/mixins-preview/with'; import { CfnBucket } from 'aws-cdk-lib/aws-s3'; import { Mixins } from '@aws-cdk/mixins-preview/core'; import { BucketVersioning, AutoDeleteObjects } from '@aws-cdk/mixins-preview/aws-s3/mixins'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'CdkSampleStack'); const bucket = new CfnBucket(stack, 'MyBucketApply'); Mixins.of(bucket) // Mixins .apply(new BucketVersioning()) // bucket に BucketVersioning を適用 .apply(new AutoDeleteObjects()); // bucket に AutoDeleteObjects を適用 new CfnBucket(stack, 'MyBucketWith') .with(new BucketVersioning()) // Construct の with メソッドで BucketVersioning を適用 .with(new AutoDeleteObjects()); // Construct の with メソッドで AutoDeleteObjects を適用
また、Aspects のように特定のスコープ配下の全てのリソースに対して適用することもできます。
import * as cdk from 'aws-cdk-lib'; import '@aws-cdk/mixins-preview/with'; import { BucketVersioning } from '@aws-cdk/mixins-preview/aws-s3/mixins'; import { Mixins, ConstructSelector } from '@aws-cdk/mixins-preview/core'; import { Construct } from 'constructs'; import { CfnBucket } from 'aws-cdk-lib/aws-s3'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'CdkSampleStack'); const construct = new Construct(stack, 'MyConstruct'); // construct 配下の全てのリソースに適用 Mixins.of(construct).apply(new BucketVersioning()); // construct 配下の特定のタイプのリソースにのみ適用 Mixins.of(construct, ConstructSelector.resourcesOfType(CfnBucket.CFN_RESOURCE_TYPE_NAME)) // CfnBucket に限定 .apply(new BucketVersioning()); // construct 配下の特定の ID パターンにマッチするリソースにのみ適用 Mixins.of(construct, ConstructSelector.byId('.*-prod-.*')) // ID が "-prod-" を含むリソースに限定 .apply(new ProductionSecurityMixin()); // ProductionSecurityMixin は自作 Mixins の例
Mixins の種類
Mixins には、いくつかの種類のパターンが用意されています。
- サービス間 Mixins
- リソース固有 Mixins
- L1 プロパティ Mixins
- ログ配信 Mixins
サービス間 Mixins
こちらは、複数の AWS サービスに共通して適用できるタイプの Mixins です。
例えば EncryptionAtRest は、暗号化が可能な AWS リソースに対して共通して暗号化を有効化する Mixins です。
※EncryptionAtRest Mixins はまだ現時点での CDK のリリースには導入されていませんが、README の例で紹介されています。恐らく近いうちに導入されると思われるため、本記事でもその例を使用します。
import { Mixins } from '@aws-cdk/mixins-preview/core'; import { App, Stack } from 'aws-cdk-lib'; import { CfnLogGroup } from 'aws-cdk-lib/aws-logs'; import { CfnBucket } from 'aws-cdk-lib/aws-s3'; const app = new App(); const stack = new Stack(app, 'MyStack'); const bucket = new CfnBucket(stack, 'Bucket'); Mixins.of(bucket).apply(new EncryptionAtRest()); const logGroup = new CfnLogGroup(stack, 'LogGroup'); Mixins.of(logGroup).apply(new EncryptionAtRest());
リソース固有 Mixins
それぞれの AWS サービス(リソース)固有の Mixins も用意されています。
例えば、S3 バケットに対してカスタムリソース Lambda を使用してオブジェクトを自動削除する AutoDeleteObjects や、バージョニングを有効化する BucketVersioning、バケットポリシーに IAM ポリシーステートメントを追加する BucketPolicyStatementsMixin などがあります。
この Mixins を L1 Construct に適用することで、L2 Construct を使用せずとも L2 Construct と同様の抽象化を導入できます。
バージョニングは L1 Construct だけでも簡単に有効化できますが、Aspects のように複数のリソースに対して一括で適用する場合などに便利です。
import { AutoDeleteObjects, BucketVersioning, BucketPolicyStatementsMixin, } from '@aws-cdk/mixins-preview/aws-s3/mixins'; import { Mixins } from '@aws-cdk/mixins-preview/core'; import { App, Stack } from 'aws-cdk-lib'; import { PolicyStatement, AnyPrincipal, PolicyDocument } from 'aws-cdk-lib/aws-iam'; import { CfnBucket, CfnBucketPolicy } from 'aws-cdk-lib/aws-s3'; const app = new App(); const stack = new Stack(app, 'MyStack'); const bucket = new CfnBucket(stack, 'Bucket'); Mixins.of(bucket).apply(new AutoDeleteObjects()); Mixins.of(bucket).apply(new BucketVersioning()); const bucketPolicy = new CfnBucketPolicy(stack, 'BucketPolicy', { bucket: bucket, policyDocument: new PolicyDocument(), }); Mixins.of(bucketPolicy).apply( new BucketPolicyStatementsMixin([ new PolicyStatement({ actions: ['s3:GetObject'], resources: ['*'], principals: [new AnyPrincipal()], }), ]), );
L1 プロパティ Mixins
こちらは、L2 Construct にまだ導入されていない L1 プロパティを簡単に適用できるようにする Mixins です。
例えば L2 Construct の with() メソッドに、CfnBucketPropsMixin という L1 プロパティを適用する Mixins を渡すことで、L2 Construct にまだ導入されていない L1 プロパティなどを型付きで適用できます。
従来では、L2 Construct に L1 プロパティを適用するにはエスケープハッチを使用する必要がありましたが、型安全性がないという問題がありました。Mixins を使用することでより簡単に型付きで適用できるようになります。
import * as cdk from 'aws-cdk-lib'; import '@aws-cdk/mixins-preview/with'; import { CfnBucketPropsMixin } from '@aws-cdk/mixins-preview/aws-s3/mixins'; import { Bucket } from 'aws-cdk-lib/aws-s3'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'CdkSampleStack'); new Bucket(stack, 'Bucket').with( new CfnBucketPropsMixin({ versioningConfiguration: { status: 'Enabled' }, publicAccessBlockConfiguration: { blockPublicAcls: true, blockPublicPolicy: true, }, }), );
また、L1 プロパティ Mixins では、MERGE と OVERRIDE の 2 種類のマージ戦略が用意されています。
- MERGE (デフォルト): 既存のプロパティに、指定したプロパティをマージ
- OVERRIDE: 既存のプロパティを、指定したプロパティで上書き
import * as cdk from 'aws-cdk-lib'; import '@aws-cdk/mixins-preview/with'; import { CfnBucketPropsMixin } from '@aws-cdk/mixins-preview/aws-s3/mixins'; import { Mixins } from '@aws-cdk/mixins-preview/core'; import { PropertyMergeStrategy } from '@aws-cdk/mixins-preview/mixins'; import { CfnBucket } from 'aws-cdk-lib/aws-s3'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'CdkSampleStack'); const bucket = new CfnBucket(stack, 'Bucket'); bucket.versioningConfiguration = { status: 'Enabled' }; // MERGE // versioningConfiguration: { status: 'Enabled', newProperty: 'Disabled' } になる // -> status: 'Enabled' は残る Mixins.of(bucket).apply( new CfnBucketPropsMixin( { versioningConfiguration: { newProperty: 'Disabled' } }, { strategy: PropertyMergeStrategy.MERGE }, ), ); // OVERRIDE // versioningConfiguration: { newProperty: 'Disabled' } になる // -> status: 'Enabled' が消える Mixins.of(bucket).apply( new CfnBucketPropsMixin( { versioningConfiguration: { newProperty: 'Disabled' } }, { strategy: PropertyMergeStrategy.OVERRIDE }, ), );
先ほど紹介した 2 種類の Mixins は CDK リポジトリ側で都度実装されるのに対し、こちらの方では CDK リポジトリ側で全ての L1 Construct に対応する Mixins が自動生成される仕組みになっています。
ログ配信 Mixins
Vended logs 配信のための Mixins も提供されています。
以下は、CfnDistributionLogsMixin という CloudFront Distribution 固有の Mixins ですが、他にもいくつかの AWS サービスに対して Vended logs の Mixins が提供されています(CfnUserPoolLogsMixin, CfnVPCLogsMixin, CfnLoadBalancerLogsMixin, etc...)。
import * as cdk from 'aws-cdk-lib'; import '@aws-cdk/mixins-preview/with'; import { Bucket } from 'aws-cdk-lib/aws-s3'; import { CfnDistributionLogsMixin } from '@aws-cdk/mixins-preview/aws-cloudfront/mixins'; import { Distribution } from 'aws-cdk-lib/aws-cloudfront'; import { S3BucketOrigin } from 'aws-cdk-lib/aws-cloudfront-origins'; import { LogGroup } from 'aws-cdk-lib/aws-logs'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'CdkSampleStack'); const bucket = new Bucket(stack, 'MyBucket'); const distribution = new Distribution(stack, 'Distribution', { defaultBehavior: { origin: S3BucketOrigin.withOriginAccessControl(bucket), }, }); // Create log destination const logGroup = new LogGroup(stack, 'DeliveryLogGroup'); // Configure log delivery using the mixin distribution.with(CfnDistributionLogsMixin.CONNECTION_LOGS.toLogGroup(logGroup));
こちらのログ配信 Mixins も、対応する AWS サービスごとに CDK リポジトリ側で自動生成される仕組みになっています。
エラーハンドリング
requireAll と requireAny
Mixins を apply() メソッドで適用した場合、その Mixins がサポートされていないリソースに対しては処理をスキップします。
Mixins を適用するスコープ配下に Mixins がサポートされていないリソースがあるかどうかをチェックしたい場合、requireAll() もしくは requireAny() メソッドを使用してください。
requireAll() メソッドは、スコープ配下の全てのリソースが Mixins をサポートしていることを要求します。もしサポートされていないリソースが 1 つでもあればエラーを投げます。
requireAny() メソッドは、スコープ配下のいずれかのリソースが Mixins をサポートしていることを要求します。もしサポートされているリソースが 1 つもなければエラーを投げます。
// construct 配下に EncryptionAtRest がサポートされていないリソースがある場合はスキップする Mixins.of(construct).apply(new EncryptionAtRest()); // construct 配下の全てのリソースが BucketVersioning をサポートしていない場合はエラーを投げる Mixins.of(construct).requireAll().apply(new BucketVersioning()); // construct 配下のいずれかのリソースが BucketVersioning をサポートしていれば適用する Mixins.of(construct).requireAny().apply(new BucketVersioning());
report と selectedConstructs
Mixins の適用結果をもとに手動でアサーションなどを行うための report と selectedConstructs というメソッドも提供されています。
report は、Mixins が正常に適用されたリソースの情報を取得するために使用します。戻り値は MixinApplication インターフェースの配列で、どの Construct にどの Mixin が適用されたかを確認できます。
selectedConstructs は、Mixins.of() の第 2 引数(もしくは未指定)で Mixins の適用対象を絞り込まれた Construct のリストを取得するために使用します。戻り値は IConstruct インターフェースの配列で、Mixin が適用される前にどの Construct が対象となったかを確認できます。
import * as cdk from 'aws-cdk-lib'; import '@aws-cdk/mixins-preview/with'; import { BucketVersioning } from '@aws-cdk/mixins-preview/aws-s3/mixins'; import { Mixins } from '@aws-cdk/mixins-preview/core'; import { Queue } from 'aws-cdk-lib/aws-sqs'; import { Bucket, CfnBucket } from 'aws-cdk-lib/aws-s3'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'CdkSampleStack'); new Bucket(stack, 'MyBucket'); new Queue(stack, 'MyQueue'); // Get an application report for manual assertions const report = Mixins.of(stack).apply(new BucketVersioning()).report; report.forEach(({ construct, mixin }) => { cdk.Annotations.of(stack).addInfoV2( `mixins-report:${mixin.constructor.name}`, `Applied mixin ${mixin.constructor.name} to construct ${construct.node.path}`, ); }); // Get the list of constructs that were selected by the selector const constructs = Mixins.of( stack, ConstructSelector.resourcesOfType(CfnQueue.CFN_RESOURCE_TYPE_NAME), ).apply(new BucketVersioning()).selectedConstructs; constructs.forEach((construct) => { cdk.Annotations.of(stack).addInfoV2( `mixins-selected:${construct.node.path}`, `Selected construct: ${construct.node.path}`, ); });
上記のコードの場合、cdk deploy 時に以下のような出力が得られます。
❯ npx cdk deploy [Info at /CdkSampleStack] Applied mixin BucketVersioning to construct CdkSampleStack/MyBucket/Resource [ack: mixins-report:BucketVersioning] [Info at /CdkSampleStack] Selected construct: CdkSampleStack/MyQueue/Resource [ack: mixins-selected:CdkSampleStack/MyQueue/Resource]
カスタム Mixins の作成
IMixin インターフェースを実装することで簡単にカスタム Mixins を作成できます。
また、Mixin 抽象クラスを継承することで、IMixin の一部がすでに実装されているものを作成できます。IMixin を用いて直接実装するのではなく、Mixin を拡張することが推奨されるようです。使用感はほとんど変わりませんが、将来的な移行が容易になります。
以下の例は、S3 バケットに対してバージョニングを有効化するカスタム Mixins の例です。
// or class CustomVersioningMixin implements IMixin { class CustomVersioningMixin extends Mixin { supports(construct: any): boolean { return construct instanceof s3.CfnBucket; } applyTo(bucket: any): void { bucket.versioningConfiguration = { status: 'Enabled', }; } } const bucket = new s3.CfnBucket(stack, 'MyBucket'); Mixins.of(bucket).apply(new CustomVersioningMixin());
Aspects との違い
Mixins は、特定のスコープのリソースのプロパティを変更するという点では Aspects と似ていますが、適用タイミングが異なります。
Aspects は呼び出し時ではなく、CDK アプリケーションの合成の後ろの方の過程(CDK のアプリケーションライフサイクルでいうと Construct 生成が終わった後の Prepare フェーズ)で実行されます。
つまり、Aspects は CDK アプリケーションの中で定義された全ての Construct が生成された後に実行されるのに対し、Mixins は呼び出されるタイミングで即座に実行されます。
これは、Mixins は命令型プログラミングの形式であるのに対し、Aspects は宣言型プログラミングの形式であると言えます。
- Aspects
const construct = new Construct(scope, 'MyConstruct'); new Bucket(construct, 'MyBucket1'); // これより下の Construct が生成された後に実行される Aspects.of(construct).add(new CustomVersioningAspect()); // Aspects は MyBucket2 にも適用される new Bucket(construct, 'MyBucket2');
- Mixins
const construct = new Construct(scope, 'MyConstruct'); new Bucket(construct, 'MyBucket1'); // この時点で実行される Mixins.of(construct).apply(new CustomVersioningMixin()); // Mixins は MyBucket2 には適用されない new Bucket(construct, 'MyBucket2');
Mixins の RFC によると、変更を加える場合には Mixins を使用し、動作を検証する場合には Aspects を使用することが推奨されています。
We recommend to use Mixins to make changes, and to use Aspects to validate behaviors.
他にも以下のように、Mixins と Aspects には以下のような違いがあるそうです。
With mixins, you make explicit decisions about each construct's capabilities. With aspects, you set policies that the CDK applies automatically during synthesis. Mixins give you precise control and type safety, while aspects provide broad governance and compliance enforcement.
- Mixins
- 各 Construct の機能について明示的に決定できる
- 正確な制御と型安全性を提供
- Aspects
- CDK が合成中に自動的に適用するポリシーを設定できる
- 広範なガバナンスとコンプライアンスの強制を提供
また RFC では、Aspects と Mixins を相互に変換できる仕組みが導入される旨が書いてありますが、v2.229.0 時点ではまだこの機能は導入されていません。
// Applies the aspect immediately Mixins.of(scope).apply(Shims.fromAspect(new TaggingAspect({ Environment: 'prod' }))); // Delays application of the Mixin to the synthesis phase Aspects.of(scope).add(Shims.fromMixin(new EncryptionAtRest()));
Property Injectors との違い
Property Injectors とは、App や Stack、Construct 内の、「特定の種類の L2 Construct(一部の L3 Construct も含む)」のすべてに対して、プロパティ(props)を一元的に書き換えるという機能です。AWS CDK v2.196.0で導入されました。
export class MyBucketPropsInjector implements IPropertyInjector { public readonly constructUniqueId: string; constructor() { this.constructUniqueId = Bucket.PROPERTY_INJECTION_ID; } public inject(originalProps: BucketProps, _context: InjectionContext): BucketProps { return { blockPublicAccess: BlockPublicAccess.BLOCK_ALL, ...originalProps, }; } } const app = new App(); PropertyInjectors.of(app).add(new MyBucketPropsInjector());
Property Injectors も Mixins と似ている機能ですが、抽象化を適用したい場合には Mixins、デフォルトの動作を変えたい場合(=ブループリントとして使いたい場合)には Property Injectors を使用することが推奨されています。
また、以下のような違いもあります。
- Mixins
- 適用対象は L1 Construct + L2 Construct
- スコープを絞ることが多い(特定の Construct など)
- Property Injectors
- 適用対象は L2 Construct (一部 L3 Construct も)
- スコープが広いことが多い(App 単位など)
Property Injectors に関する詳細は、以下の記事をご覧ください。
Visitor パターンとの関係
Mixins も Aspects も、どちらも GoF デザインパターンの Visitor パターンをベースに設計されています。
Visitor パターンについては、以下のAWS CDK内部実装で使われているGoFデザインパターンという記事で詳しく解説していますので、興味がある方はぜひご覧ください。
EventBridge イベントパターン
Mixins パッケージでは、EventBridge のイベントパターンを、型付きで安全に生成するための仕組みも提供されています。(これ自体は Mixins ではないのですが、同じパッケージに含まれています。)
こちらは、L1 Construct にも L2 Construct にも対応しています。
例えば、S3 バケットのイベントでは BucketEvents というクラスを使用して、S3 バケットのオブジェクト作成イベントのパターンを型付きで生成できます。
import * as cdk from 'aws-cdk-lib'; import '@aws-cdk/mixins-preview/with'; import { BucketEvents } from '@aws-cdk/mixins-preview/aws-s3/events'; import * as events from 'aws-cdk-lib/aws-events'; import * as targets from 'aws-cdk-lib/aws-events-targets'; import { Function } from 'aws-cdk-lib/aws-lambda'; import { Bucket, CfnBucket } from 'aws-cdk-lib/aws-s3'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'CdkSampleStack'); const fn = new Function(stack, 'Function', { ... }); // Works with L2 constructs const bucket = new Bucket(stack, 'Bucket'); // BucketEvents from Mixins const bucketEvents = BucketEvents.fromBucket(bucket); new events.Rule(stack, 'Rule', { eventPattern: bucketEvents.objectCreatedPattern({ object: { key: events.Match.wildcard('uploads/*') }, eventMetadata: { region: events.Match.prefix('us-'), version: ['0'], }, }), targets: [new targets.LambdaFunction(fn)], }); // Also works with L1 constructs const cfnBucket = new CfnBucket(stack, 'CfnBucket'); // BucketEvents from Mixins const cfnBucketEvents = BucketEvents.fromBucket(cfnBucket); new events.CfnRule(stack, 'CfnRule', { state: 'ENABLED', eventPattern: cfnBucketEvents.objectCreatedPattern({ object: { key: events.Match.wildcard('uploads/*') }, eventMetadata: { region: events.Match.prefix('us-'), version: ['0'], }, }), targets: [{ arn: fn.functionArn, id: 'L1' }], });
このイベントパターンは、AWS Event Schema Registry で利用可能な EventBridge イベントに対して、CDK リポジトリ側で自動生成されます。
例えば、S3 イベントの場合は以下のようなパターンが用意されています。
objectCreatedPattern()- オブジェクト作成イベントobjectDeletedPattern()- オブジェクト削除イベントobjectTagsAddedPattern()- オブジェクトタグ追加イベントawsAPICallViaCloudTrailPattern()- CloudTrail API 呼び出しイベント
最後に
Mixins は、今後の CDK の肝となる重要な機能です。
まだ Developer Preview のためまだまだ機能や動作が不十分な点もありますが、今後の CDK の使い方が大きく変わる可能性があるため、ぜひ注目しておきたいところです。