Build a global serverless application in 30 minutes with AWS CDK.

Brian Foody
Feb 29 · 5 min read

Chapter two of the Lambda Lego Series

The worlds your oyster!

So you’ve tasted the fruits of serverless in a single region and now you want to expand globally?

But if you are like me you’ve been scratching your head looking for a few missing pieces of the puzzle.

How do I route traffic to the closest region? How do I ensure that if my customer moves regions they won’t experience any issues?

Show me the code

Here’s the short of it;

Explain this code

Well let’s fill in those gaps and leave you with a more resilient architecture that can handle global customer traffic. Or in AWS lingo — multi region deployments.

Single region

First let’s look at the architecture for a single region. Pretty straightforward.

We have API Gateway in front of our lambdas, a regular old DynamoDB table, and then we have an A record in Route53 pointing to our API Gateway Domain.

While this is fine and dandy for most basic projects given the high regional availability of Serverless, as projects go global this will not scale. Requests to the region can be slow from elsewhere in the world and as revenue increases the risk of a regional outage becomes increasingly a concern.

Single Region Serverless

Going global

So let’s fill in the missing pieces to take this global. There’s a few changes needed to accomplish this which we will go through in CDK.

1) We want our application stack to be deployable in each region — no config for global services like Route53 like you may have had above.

2) We need to switch to Global DynamoDB tables to ensure data is nearby the stack. AWS will manage the syncing nicely.

3) Our API Gateway Domain’s will need to switch to Regional instead of Edge along with our API’s

4) We remove our A record in Route53 and switch to a latency based traffic policy which dynamically routes to the nearest resource.

For this article I’m going to assume you already have a domain in Route53 for your website and it’s called multi.com

Regional resources

We are going to deploy our service in two regions; ap-southeast-2 and eu-central-1.

Note that all of these resources are created in EACH region. We’ll add the traffic policy to manage routing afterwards.

First let’s create our regional API for each region.

this.api = new RestApi(this, “RegionalApi”, {
endpointTypes: [EndpointType.REGIONAL]
});

Now we’re going to need a certificate for the regional domain we put in front of this;

const certificate = new certificatemanager.Certificate(this, "ApiCertificate", {
domainName: "api.multi.com",
validationMethod: certificatemanager.ValidationMethod.DNS
});

And now we simply create our regional custom domain with the certificate.

const domain = new DomainName(this, “APIDomain”, {
domainName: “api.multi.com”,
certificate,
endpointType: EndpointType.REGIONAL
});

For this example we are going to route all traffic to our single API instance so we’ll add a base path mapping to our custom domain to specify that;

new CfnBasePathMapping(this, “Resource”, {
basePath: “(none)”,
domainName: domain.domainName,
restApiId: this.api.restApiId,
stage: this.api.deploymentStage.stageName
});

And now we simply create a health check for this instance to ensure that it is healthy.

new CfnHealthCheck(this, "ApiHealthCheck", {
healthCheckConfig: {
port: 443,
type: "HTTPS",
resourcePath: "/prod/health/check",
fullyQualifiedDomainName: `${this.api.restApiId}.execute-api.${this.region}.amazonaws.com`,
requestInterval: 30,
failureThreshold: 2
}
});

If the health check fails in any region our traffic policy will ensure that no traffic is sent to the problem region adding a greater level of assurance to your Serverless architectures.

Our health check function

Add the region in a response on our health function to ensure you are being directed to the right one in each region.

const checkHealthHandler = new Function(this, "CheckTrackHandler", {
runtime: Runtime.NODEJS_10_X,
code: Code.asset("./lib/src"),
handler: "health/get.main",
layers: [props.root.layer],
memorySize: 128
});
// Endpoints
api.addResource("check").addMethod(
"GET",
new LambdaIntegration(checkHealthHandler, {
allowTestInvoke: false
})
);

Deploying our regional resources

Deploying the same stack to multiple regions is almost too easy. Simply specify the stack for each region;

// Create a new CDK app
const app = new App();
// Add your stacks to it
new Stack(app, "api-multi-oz", {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: "ap-southeast-2"
}
});
new Stack(app, "api-multi-eu", {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: "eu-central-1"
}
});
app.synth();

And then simply deploy;

cdk deploy --require-approval never --color=always "*"

Adding a traffic policy

Unfortunately right now I must commit the easiest of AWS sins to fall to — manually creating a resource through the AWS console.

Traffic policies are currently not supported by Cloudformation and so not supported by CDK. I can probably automate this through the AWS SDK and I’ll update the article when I do.

But Route53 is one of the rare places I tend to do some manual work in given it’s a global service and AWS’ devops tooling in this area also seems to be lacking.

So let’s create our traffic policy through the pretty UI AWS have given us to lure us into bad practice.

Head on over to Route53 and click “Create traffic policy”

Latency Based traffic

By creating a Latency based rule and assigning our two endpoints AWS will basically learn which API is closer to our customer and route them to it. Pretty neat.

And then we just need to create the policy record. This is the nasty part of multi-region as we have to absorb a baseline $50 cost for this record. It violates the serverless principles (pay as you go) but for the simplicity of global dynamic routing I’m willing to take this one on the chin.

And that’s it. Go grab a cup of tea, that’s enough for today 😉.

Me

An AWS Certified Solutions Architect Professional with a passion for retiring servers.

Hit me up on LinkedIn if you need any help with this stuff.

Lambda Lego

Solving problems the Serverless way

Brian Foody

Written by

Building through play.

Lambda Lego

Solving problems the Serverless way

More From Medium

More on Serverless from Lambda Lego

More on Serverless from Lambda Lego

More on Serverless from Lambda Lego

Lambda Lego — Rules

5

More on Lambda from Lambda Lego

More on Lambda from Lambda Lego

Lamba Lego — Intro

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade