Top 10 best practices for serverless.yml

Home Blog Top 10 best practices for serverless.yml
The Serverless Framework logo on a background of clouds.

The Serverless Framework is one of the oldest (and still going strong!) deployment frameworks around for serverless applications. It’s my framework of choice and enjoys a great deal of support from the community in terms of contributions as well as plugins. In fact, its ecosystem of plugins is one of its greatest strengths compared with other deployment frameworks.

The Serverless Framework gives you a number of best practices out of the box, such as:

  • Enforcing a consistent naming convention.
  • Generating the minimum IAM permissions to other services so they can invoke your Lambda functions.
  • Supporting the use of SSM parameter store for storing sensitive data securely with SecureStrings.

But there are still an awful lot of things for us to do to ensure our applications are secure and robust. So here are my top 10 best practices that you should adopt when working with the Serverless Framework.

1. No wildcards in IAM role statements

Serverless applications can be more secure than their container and VM counterparts. But, we still need to do our part and make sure we don’t overprovision our functions with access.

We should follow the principle of least privilege and grant our functions the minimal amount of access they need. And that means granting permissions to perform specific operations against specific resources.

2. One IAM role per function

By default, the Serverless Framework uses a shared role for all the functions in the serverless.yml. This too violates the principle of least privilege as functions would gain unnecessary access through the shared role.

Instead, you should use the serverless-iam-roles-per-function plugin and define IAM roles for each function.

3. Configure DLQ for async functions

When you define functions that are invoked by async event sources (see here), you should configure a separate DLQ for each function. Services that invoke Lambda functions asynchronously provide built-in retry with exponential delay. However, if the function errors persistently then the invocation events can be lost forever if you haven’t configured a DLQ.

4. Configure framework version range

If you are using an instance of the Serverless Framework that is installed on your machine (or on the CI server), then you should add the frameworkVersion property to the serverless.yml.

frameworkVersion: ‘>=1.0.0 <2.0.0’

This checks that you’re using a version of the Serverless Framework that is compatible with the current serverless.yml.

5. Configure CloudFormation deploy role

The Serverless Framework lets you pass a dedicated deployer role to CloudFormation to run deployments with.

cfnRole: arn:aws:iam::XXXXXX:role/role

You can use a different role for each project, or each team and apply the principle of least privilege to the deployment pipeline. This approach also combines well with attribute-based access control (ABAC). For example, the deployer role for team A can be restricted to create and delete (for rollbacks) DynamoDB tables with the tag “Team=TeamA”.

6. Configure stack tags

Tags help you find resources easier and you can even use them to track your AWS spending. By default, the Serverless Framework inserts the STAGE tag to the generated CloudFormation template.

However, you should consider adding other custom tags using the stackTags property. Common tags to consider include Author, Team, Feature, Cost Center and Region. Unfortunately, CloudFormation doesn’t propagate its tags to some resources such as CloudWatch log groups. You can address this limitation by deploying the propagate-cfn-tags SAR app to your account.

7. When using VPCs, configure at least 2 subnets

When configuring your functions with VPC access, make sure you configure at least 2 dedicated subnets for Lambda. This mitigates the risk of IP exhaustion in the subnet and limits the blast radius to Lambda functions.

However, given the recent announcement of improved VPC networking for Lambda, this would no longer be necessary once the improvement has been rolled out to your account.

8. Use Fn::Sub instead of Fn::Join for clarity

Most of the time Fn::Join is used to construct ARNs and URLs out of different parts. In such cases, you should use Fn::Sub instead, which makes for much more readable code.

See more examples here.

9. For Node.js functions, use webpack to improve cold start and reduce package size

For Node.js functions, the Initialization time is a big part of the cold start time and can vary greatly depending on how many dependencies you have.

Webpack can help reduce Initialization time significantly. You should use the serverless-webpack plugin to run webpack automatically every time you deploy your code.

See here for more details.

10. Break large serverless.yml into multiple files

The Serverless Framework lets you reference external YML and JSON files. When your serverless.yml gets too big, you should break it up into smaller files and reference them back in the main serverless.yml. This helps you keep the serverless.yml file manageable.

And that’s it! 10 things you should be doing when working with the Serverless Framework. Let us know on Twitter or LinkedIn if you don’t agree with our selection, or maybe we have missed any practices that you think everyone should adopt.

The article, Top 10 Serverless Best Practices, first appeared on the
website of Datree, the policy enforcement platform.