Code Included!
From the second you deploy your resources into the AWS Cloud, you have access to a global computing network. Something unimaginable in the past and grossly underutilized even by today’s standards. In this article, I’ll show you two simple ways you can begin leveraging the power of global deployments with CDK.
If you plan on following along, make sure you have completed these tasks.
This design implements a “Root” stack that then deploys the subsequent region-specific stacks. The root stack will be deployed into the default region associated with the profile (us-east-1 unless specified). There are several things achieved with this.
Here is an example of the root stack taken from here in the repository.
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { AppStack } from './app-stack/app-stack'; export class MultiRegionExampleStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const regions = ['us-east-1', 'eu-west-1']; // store the regional stacks in an object for debugging const regionalStacks = regions.reduce((accu, region) => { const regionalStack = new AppStack(this, region, { env: { region }, }); return { ...accu, [region]: regionalStack }; }, {}); } }
If you’re familiar with the NestedStack construct, you are probably thinking “What a perfect use case!”. Sadly at the time of writing this, it seems that NestedStacks have to be deployed in the same region that the source stack is deployed in. I don’t believe this is a CDK limitation, but instead a CloudFormation one. There is an open issue with some discussion around implementing this in CDK, however it does seem to be rather complicated. But hey if this is a blocker for you, get active and let them know!
Another Cloudformation feature that is commonly used to solve this problem is Stack Sets. At the time of writing this, there is no support out of the box in CDK. But there is a CDK Labs construct in the experimental phase you can try out. But per their readme, I would avoid getting overly tied to its implementation until it is generally released.
In theory, you shouldn’t need to reference values from an application stack deployed in Region A in an application stack deployed in Region B. As they are siblings, so dependencies should be managed via prop drilling. However reality is often finicky, so if you do end up in this situation, I would recommend storing the dependency value in ParameterStore and dynamically referencing it in the dependent stack. If you’d like to learn more, I wrote a deep-dive here that you may find useful.
For a more traditional IaC experience, we can remove the root stack. Opting to instead deploy the stacks directly. We do lose some of the “superpowers” the first option provides, with the benefit of having something simpler to reason about.
There are two main options I’ve observed
Instantiate your region-specific stack however many times you need in the /bin/app.ts file. You can find a full example here in the CDK docs. As well as this branch in the repository.
Instantiate your region-specific stack once in the /bin/app.ts file, and use the cdk deploy command to deploy it to the regions you desire. This branch has one approach you might take.
While this does supply you with a more traditional experience there are still benefits to using CDK, that you wouldn’t have access to otherwise.
Higher level constructs
Component libraries
With CDK, it’s never been easier to duplicate resources into multiple AWS regions. You can bring your code closer to your customers and increase your fault tolerance with just a few clicks.
Best of luck and hope this helps!