by Michael Kaiser and Momo Kornher
We are excited to announce the developer preview of CDK Mixins, a new feature of the AWS Cloud Development Kit (CDK) that fundamentally changes how developers compose and reuse infrastructure abstractions. CDK Mixins enable you to apply sophisticated features to any construct whether L1, L2, or custom without being locked into specific implementations. This new mechanism addresses one of the most persistent challenges in infrastructure as code: the tension between comprehensive AWS coverage and sophisticated abstractions.
Background
The AWS Cloud Development Kit (CDK) is an open-source software development framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation. It contains pre-written modular and reusable cloud components known as constructs. Constructs are the basic building blocks representing one or more AWS CloudFormation resources and their configuration.
Traditionally, CDK constructs are organized into three levels. L1 constructs map directly to CloudFormation resources and provide day-one access to new AWS features. L2 constructs offer higher-level abstractions with convenience methods, security defaults, and helper functions. L3 constructs (also known as patterns) combine multiple resources to solve specific use cases. However, this architecture creates a fundamental trade-off: customers must choose between immediate access to new AWS features (L1) and sophisticated abstractions (L2/L3). Enterprise customers report needing to customize L2 constructs, often rebuilding entire construct libraries to meet their specific requirements.
CDK Mixins solve this problem by decoupling abstractions from construct implementations. Instead of bundling all features into monolithic L2 constructs, Mixins allow you to compose exactly the capabilities you need, apply them to any construct type, and maintain full access to underlying CloudFormation properties.
What are CDK Mixins?
CDK Mixins are composable, reusable abstractions that can be applied to constructs after they are created. Think of them as modular capabilities that you can mix and match to build exactly the infrastructure you need. Unlike traditional L2 constructs that bundle all features together, Mixins give you fine-grained control over which abstractions apply.
Key benefits include:
Universal Compatibility: Apply the same abstractions to L1 constructs, L2 constructs, or custom constructs
Composable Design: Mix and match features without inheriting unwanted behaviors
Cross-Service Abstractions: Create custom mixins that work across different AWS services
Day-One Coverage: Access new AWS features immediately while keeping existing L2 or L3 constructs
Type Safety: Maintain compile-time guarantees and IDE support
Using CDK Mixins
CDK Mixins are available starting in the @aws-cdk/mixins-preview package. They can be used with both L1, L2 and L3 constructs:
// CDK Mixins can be used with L1s
new s3.CfnBucket(stack, "MixinsL1DemoBucket")
// Use the fluent .with() syntax (only available in JavaScript/TypeScript during preview)
.with(new s3Mixins.EnableVersioning());
// ... or with L2s
new s3.Bucket(stack, "MixinsL2DemoBucket")
// Cfn Property Mixins provide type-safe fallbacks for L2s
// and configuration after initial creation
.with(new s3Mixins.CfnBucketPropsMixin({
objectLockEnabled: true,
objectLockConfiguration: {
objectLockEnabled: "Enabled",
rule: {
defaultRetention: {
mode: "COMPLIANCE",
days: 30,
},
},
},
}));
You can also use Mixins.of() to apply Mixins in other languages or with more control over which constructs receive the mixin:
// Use Mixins.of() to apply Mixins in other languages
// This also gives you more options to apply only to certain constructs
Mixins.of(stack, /* optional */ ConstructSelector.byId(/^MixinsL1DemoBucket$/))
.apply(new s3Mixins.AutoDeleteObjects());
Apply mixins at scale to entire construct trees or specific resource types:
// Apply your Mixins to the whole app
Mixins.of(app).apply(new MyDataRecovery());
// ... or only to some constructs
Mixins.of(app, ConstructSelector.resourcesOfType(s3.CfnBucket.CFN_RESOURCE_TYPE_NAME)).apply(new MyDataRecovery());
Creating Custom Mixins
Creating your own Mixins is straightforward they are simple classes implementing the Mixin interface. The supports() method determines which constructs the mixin can be applied to, and applyTo() modifies the construct. Here's a custom mixin that enables data recovery features across both S3 buckets and DynamoDB tables:
// It's easy to develop your own Mixins
class MyDataRecovery implements Mixin {
public supports(construct: IConstruct): boolean {
// Mixins can be cross-service and support different resources at once
return construct instanceof s3.CfnBucket || construct instanceof dynamodb.CfnTable;
}
public applyTo(construct: IConstruct): IConstruct {
if (construct instanceof s3.CfnBucket) {
construct.versioningConfiguration = {
status: 'Enabled',
};
}
if (construct instanceof dynamodb.CfnTable) {
construct.pointInTimeRecoverySpecification = {
pointInTimeRecoveryEnabled: true,
};
}
return construct;
}
}
Once defined, you can apply your custom mixin to resources:
// ... and to use them:
new s3.Bucket(stack, 'AcmeBucket');
new dynamodb.TableV2(stack, 'AcmeTable', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
});
// Apply your Mixins to the whole app
Mixins.of(app).apply(new MyDataRecovery());
// ... or only to some constructs
Mixins.of(app, ConstructSelector.resourcesOfType(s3.CfnBucket.CFN_RESOURCE_TYPE_NAME)).apply(new MyDataRecovery());
This pattern enables organizations to create reusable abstractions that work across any construct type, ensuring consistent security and compliance policies throughout their infrastructure.
Mixin Behavior Control
Control whether mixins must successfully apply or can gracefully skip unsupported constructs:
// Mixin application comes in two behavior options:
// Graceful: Skips unsupported constructs
const logGroup = new logs.CfnLogGroup(stack, 'LogGroup');
Mixins.of(logGroup).apply(new s3Mixins.AutoDeleteObjects());
// Strict: Throws if any construct is not supported by the mixin
Mixins.of(logGroup).mustApply(new s3Mixins.AutoDeleteObjects());
This flexibility allows you to choose the right behavior for your use case whether you want to apply Mixins opportunistically or enforce their presence.
Getting Started
CDK Mixins are available in developer preview starting with the @aws-cdk/mixins-preview package. To get started:
- Install the package:
npm install --save-dev aws-cdk-lib @aws-cdk/mixins-preview
- Import the
.with()syntax in your stack file:
// stack.ts
import '@aws-cdk/mixins-preview/with';
- Import and use Mixins in your CDK application:
import { Mixins } from '@aws-cdk/mixins-preview/core';
- Explore the documentation for detailed examples and API references.
As this is a developer preview, we encourage you to try CDK Mixins in your applications and provide feedback. The APIs may evolve based on community input before reaching general availability.
Conclusion
CDK Mixins represent a fundamental shift in how we think about infrastructure abstractions. By decoupling capabilities from construct implementations, Mixins give you the freedom to compose exactly the infrastructure you need whether you are using L1 constructs for day-one AWS features, L2 constructs for convenience, or custom constructs for enterprise requirements.
We are excited to see what the community builds with CDK Mixins. Share your feedback, create custom Mixins, and help shape the future of infrastructure as code with AWS CDK.
For more information, check out:
Top comments (0)