While working on putting the finishing touches on v1 of Hook Relay, we decided to try using AWS Timestream, AWS' recently-released time series database. This led to a problem with deploying our stack, since we are using the Serverless Framework to deploy the Lambda functions we are using to multiple AWS regions.
The problem was that Timestream isn't yet available in all the regions we are using, so the CloudFormation stack that is being generated by the framework isn't valid in those regions that don't have Timestream. There isn't a built-in way to exclude a portion of the resources
block (the portion that creates the Timestream database and table) when deploying to specific regions, so we had to get a little creative. Here's our solution:
serverless.yml
service: hook-relay
provider:
name: aws
custom:
resources:
us-east-1: ${file(./resources/timestream.yml)}
resources:
- ${file(./resources/main.yml)}
- ${self:custom.resources.${self:provider.region}, ''}
resources/timestream.yml
Resources:
tsdb:
Type: AWS::Timestream::Database
Properties:
DatabaseName: "hook-relay-${self:custom.stage}"
tsdeliveries:
Type: AWS::Timestream::Table
Properties:
DatabaseName: !Ref tsdb
TableName: deliveries
As you can see, we use a combination of custom variables, file includes, default values, and the ability to define multiple Resources
blocks to get what we want. First we define a custom variable resources.us-east-1
that yanks in the content of the timestream.yml
file, which has the CloudFormation definition of the resources that should only be created in that one region. Then we include the contents of that variable in the resources
block by interpolating the current region as part of the variable name, with an empty string as the default fallback when that custom variable doesn't exist (e.g., when deploying to eu-central-1 via a command line option to sls deploy
). Finally, we include the contents of resources/main.yml
in the resources
block. This file has another CloudFormation configuration that defines the resources that should be present in each region, such as DynamoDB tables, SQS queues, etc.
With that, whenever you run sls deploy
, regardless of the region you deploy to, you'll get the AWS resources you want, without the ones you don't. Thanks to Cameron Childress for providing essential tips that led to this solution.