AWS resources tagging using Serverless framework

An explanation about how AWS resources can be tagged using the Serverless framework. Code sample is available in GitHub.

Resources tagging is an important mechanism in the AWS ecosystem. They can be used for DevOps automation and cost allocation, among other things. A tag is a pair of key and value that can assigned to most resources. A resource can have a maximum of 50 tags. AWS automatically assigns some tags with aws: prefix.

Whilst you work with the Serverless framework to develop a solution for AWS, the framework provisions the resources on your behalf. Some of those resources are provisioned explicitly, i.e. as a result of CloudFormation script inside the resources section of serverless.yml. Other resources are provisioned implicitly, as part of the conventional abstraction of the framework, e.g. API Gateway, Lambda, S3 bucket used for deployment.

Serverless framework gives you full control when it comes to tagging both explicit and implicit resources by updating the serverless.yml configuration file. Different methods are explained as follows:

1. Using provider.stackTags

All the tags specified under provider.stackTags section will be:

  • Applied to the stack which contains all the resources that the framework will create for a service
  • Applied to most of the resources created directly or indirectly by the framework. The reason it’s most and not all is detailed in the last section of this article.

This is the place you should use to tag your resources. It is centralised in one place and is cascaded down to most resources.

provider:
stackTags:
stackTag1: value1
stackTag2: value2

2. Using provider.tags

The provider.tags node provides a quick way to tag those resources. All tags specified under this node will be applied to all those API Gateway’s APIs and Lambdas.

provider:
tags:
provTag1: value1
provTag2: value2

3. Using provider.deploymentBucket.tags

This node is only used to tag the S3 bucket that the framework uses to deploy code to AWS.

provider:
deploymentBucket:
tags:
depBucketTag1: value1
depBucketTag2: value2

4. Using tags property for each function

Each function declaration in serverless.yml has a tags node. Those tags will be applied for the Lambda but not the API Gateway’s API.

functions:
hello:
handler: handler.hello
tags:
funcTag1: value1

5. Tags property in CloudFormation

For resources created explicitly inside serverless.yml, you can make uses of CloudFormation syntax to tag them individually.

For example, an S3 bucket:

resources:
Resources:
s3Bucket:
Type: AWS::S3::Bucket
Properties:
Tags:
- Key: directS3Tag1
Value: value1
- Key: directS3Tag2
Value: value2

or a DynamoDB table:

resources:
Resources:
dynamodbTable:
Type: AWS::DynamoDB::Table
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: postcode
AttributeType: S
KeySchema:
- AttributeName: postcode
KeyType: HASH
Tags:
- Key: directDdbTag1
Value: value1
- Key: directDdbTag2
Value: value2

6. Some exceptions

AWS Cognito’s CloudFormation syntax for tagging is weird. Firstly, it’s under UserPoolTags property, instead of the usual Tags for other resources. Secondly, the input value must be a JSON value inside YAML 🤦‍♂.

The provider.stackTags does not apply to AWS Cognito. It’s likely to be a 🐛 that can be mitigated by writing extra CloudFormation as follows:

resources:
Resources:
UserPool3:
Type: AWS::Cognito::UserPool
DeletionPolicy: Delete
Properties:
UserPoolTags:
{
"directPoolTag1": "value",
"directPoolTag2": "value"
}

UserPoolClient does not even support tagging at all.

The most likely explanation for the exceptions is the AWS engineering team ran out of time whilst developing the feature and the adoption of Cognito has yet been widespread enough to justify the additional development efforts.

Software developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store