In my previous post, I discussed my choice of AWS CDK. As a newcomer to this solution, I followed various tutorials that provided basic solutions for quickly setting up different components. However, as I added more elements—multiple DynamoDB tables, several Lambdas, and a new public endpoint for the API Gateway—to a single file, I encountered two significant challenges:
- Navigation became difficult.
- There was an increased likelihood of merge conflicts when multiple people edited the same file.
Anticipating these issues, I knew that refactoring and isolating responsibilities would be necessary. However, dealing with infrastructure is not as straightforward as working with regular code.
When attempting to extract database creation code to a separate file, I faced unexpected challenges. With CDK, removing something from the code also removes it from the infrastructure. While this works seamlessly for stateless entities like Lambdas, it creates complications for resources like DynamoDB.
In the case of DynamoDB, moving code to another file results in:
- Removal from the infrastructure, though the database remains intact in AWS; however, CDK considers it deleted.
- Attempted recreation of the database, leading to an error stating that it already exists.
From:
export class ParentFile extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
...
const dynamodbTable = new dynamodb.TableV2(this, "AName", {
tableName: "aName",
partitionKey: { name: "sessionID", type: dynamodb.AttributeType.STRING },
sortKey: { name: "timestamp", type: dynamodb.AttributeType.STRING },
});
...
}
To:
export class ParentFile extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
...
const helloWithCounter = new AnotherFile(this, "HelloHitCounter", {});
...
}
export class AnotherFile extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
...
const dynamodbTable = new dynamodb.TableV2(this, "AName", {
tableName: "aName",
partitionKey: { name: "sessionID", type: dynamodb.AttributeType.STRING },
sortKey: { name: "timestamp", type: dynamodb.AttributeType.STRING },
});
...
}
This leaves us in a situation where the database exists in AWS but not in CDK.
There are two alternative solutions:
Import the Database:
You can achieve this with code likedynamodb.TableV2.fromTableName(scope, id, "aName");
. This limits you to read-only operations such as allowing to grant access to Lambdas but .Import Existing AWS Resources to CDK:
Reference the DynamoDB creation code in the same way you initially created it and runcdk import
. This approach reimports everything, giving you full control over the database.
The steps would be as follow:
- Remove the reference to the dynamoDB (make sure that it retains the DB in AWS)
- run
cdk deploy
- Add the reference you deleted to your new file
- run
cdk import
To summarize: avoid consolidating everything in a single file. If, like me, you hastily combined components, you can now refactor your CDK stack by performing a soft delete to keep resources in AWS while excluding them from AWS CDK. Subsequently, reimport them to regain full control.
Top comments (0)