Multi-Region Serverless deployments on AWS with custom domains
Tags: webdev, serverless, aws, cloud
Published: 2021-12-20 11:48:24

In this post, I will be extending [the article](https://www.serverless.com/blog/build-multiregion-multimaster-application-dynamodb-global-tables) on [Serverless Framework](https://www.serverless.com) which we use at [FINN](https://www.finn.auto) actively, and tell you how to implement a service with custom domains and multiple regions.

# What is Serverless?

Serverless is a way of providing backend services only when needed for use (for our case: [AWS Lambda](https://aws.amazon.com/lambda/)). We will be using the [Serverless Framework](https://www.serverless.com/framework) described as Zero-friction development tooling for auto-scaling apps on [AWS Lambda](https://aws.amazon.com/lambda/).

It simply deploys your services to AWS Lambda and creates a restful API (your choice) for your service. You can attach a custom domain to any stage of your deployment.

# Steps

Now let's deploy our application to both `staging` and `production` environments with their relevant custom domains. 

In the end, we will have four deployments on both `Europe (eu-central-1)` and `US East (us-east-1)` regions with the routing setting based on `latency`:

- Domain: `stg-multi-region.saral.dev` Stage: `staging` Region: `eu-central-1`
- Domain: `stg-multi-region.saral.dev` Stage: `staging` Region: `us-east-1`
- Domain: `multi-region.saral.dev` Stage: `production` Region: `eu-central-1`
- Domain: `multi-region.saral.dev` Stage: `production` Region: `us-east-1`

## 1) Install Serverless plugins

Assuming you already [installed serverless](https://www.serverless.com/framework/docs/getting-started).
In order to manage custom domains, install [serverless-domain-manager](https://www.serverless.com/plugins/serverless-domain-manager):

```
yarn add -D serverless-domain-manager
```

Then install [stage manager](https://www.serverless.com/plugins/serverless-stage-manager):

```
yarn add -D serverless-stage-manager
```

## 2) Setup the serverless.yml

This is just an example.

```yaml
service: multi-region-service

app: myapp
org: myorg

frameworkVersion: '2'

provider:
  name: aws
  endpointType: REGIONAL
  runtime: nodejs14.x
  memorySize: 256
  stage: ${opt:stage, 'staging'}
  region: ${opt:region, 'eu-central-1'}
  tags:
    author: saral.dev

custom:
  domains:
    production: multi-region.saral.dev
    staging: stg-multi-region.saral.dev
  environments:
    staging: staging
    production: production
  customDomain:
    domainName: ${self:custom.domains.${self:provider.stage}}
    basePath: ''
    stage: ${self:provider.stage}
    createRoute53Record: true
    endpointType: 'regional'
    certificateRegion: ${opt:region, 'eu-central-1'}
    route53Params:
      routingPolicy: latency
  stages:
    - staging
    - production

plugins:
  - serverless-domain-manager
  - serverless-stage-manager
  - serverless-offline
```

## 3) Create domains with regions

- Create `stg-multi-region.saral.dev` on `eu-central-1` region:

```
serverless create_domain --stage staging
```
or
```
serverless create_domain --stage staging --region eu-central-1
```

- Create `stg-multi-region.saral.dev` on `us-east-1` region:

```
serverless create_domain --stage staging --region us-east-1
```

- Create `multi-region.saral.dev` on `eu-central-1` region:

```
serverless create_domain --stage production
```
or
```
serverless create_domain --stage production --region eu-central-1
```

- Create `multi-region.saral.dev` on `us-east-1` region:

```
serverless create_domain --stage production --region us-east-1
```

## 4) Deploy services to AWS

- Deploy `staging` on `eu-central-1` region:

```
serverless deploy --stage staging
```
or
```
serverless deploy --stage staging --region eu-central-1
```

- Deploy `staging` on `us-east-1` region:

```
serverless deploy --stage staging --region us-east-1
```

- Deploy production on eu-central-1 region:

```
serverless deploy --stage production
```
or
```
serverless deploy --stage production --region eu-central-1
```

- Deploy `production` on `us-east-1` region:

```
serverless deploy --stage production --region us-east-1
```

# How to convert an existing Edge service to Regional

By default, Serverless does not deploy regional endpoints. Let's assume you have a setup like this in your `serverless.yml`:

```yaml
customDomain:
    domainName: ${self:custom.domains.${self:custom.stage}}
    basePath: ''
    stage: ${self:custom.stage}
    createRoute53Record: true
```

Before you do any multi-region changes, you should first run the following commands and remove your custom domains because, at the moment, it's not possible to alter the endpoint type.

```
serverless delete_domain --stage staging
serverless delete_domain --stage production
```

After that, you can start steps 3 and 4 above.

Unfortunately, there will be a downtime until your deployment is done.

---------

If you want to log the region in your lambda, the environment variable `AWS_REGION` is available via AWS Lambda. So you can print it with `console.log(process.env.AWS_REGION)`. You can also check your deployments on [Serverless Dashboard](https://www.serverless.com/dashboard/). 

I hope you enjoyed the post. Don't forget to show some love. :)