Check out my new course Learn you some Lambda best practice for great good! and learn the best practices for performance, cost, security, resilience, observability and scalability.
I’m a long-time user of the Serverless framework and a big fan of its plugin system. It offers tremendous flexibility and there exists a rich ecosystem of community-driven plugins. It’s easily the Serverless framework’s greatest strength and the reason why I keep going back to it.
However, I have observed a common pattern where customers would overextend the use of plugins. A typical example is using plugins to manage log subscriptions for log aggregation.
Centralised logging is a “centralised decision” that applies to all your serverless projects. What logging service do you use? How do you ship the logs from CloudWatch to that service? Do you use Lambda directly or proxy through a Kinesis stream first?
Executing this decision at the project level has some problems:
- Copy-and-paste configuration in every
serverless.yml. It’s laborious and difficult to enforce consistency in a large organization.
- It’s difficult and risky to change that decision later. You’d need to do a coordinated rollout of every project to every environment.
Instead, for decisions that apply to ALL projects, you should build them into your platform. And by “platform”, I mean a collection of capabilities that are implemented once per account or region.
Capabilities such as:
- logs would be delivered to your chosen logging service, be it Elasticsearch, Logz.io, Loggly, NewRelic or whatever it might be.
- log retention policies are configured to X days to reduce storage cost.
- functions can record custom metrics with StatsD format log messages.
- CloudFormation tags are propagated to all resources to enable better cost tracking.
But not all decisions are applicable to all your projects. Decisions that are specific to one project, or need to be tailored for each project, should be implemented at the project level. Plugins are a good way to implement these decisions.
For instance, serverless-webpack makes it easy for you to use webpack to bundle and minimize your deployment artefact. It can have a big impact on reducing the cold start duration of your function too.
The decision to use webpack is specific to one project. It’s a decision based on the needs of that project. For example, you’re building a user-facing API using Node.js, so you care about cold start durations.
How do you implement such a platform?
In the simplest form, you can implement it using two CloudFormation templates:
- an account template for account level resources such as IAM roles, CloudTrail and S3 bucket, etc.
- a region template for regional resources such as VPCs, security groups, etc.
This approach is likely sufficient for a small startup. But it’s not going to scale for Enterprises, where you have many teams and complex security and compliance requirements. That’s where AWS Control Tower comes in.
Control Tower lets you template the baseline configuration for new accounts. You can then use the account factory to quickly provision them. If you’re new to Control Tower, then check out this session from re:inforce 2019.
The Serverless Application Repository (SAR) is a good way to make reusable components that can be plugged into your platform. Here are some SAR apps that I have published to implement platform-level capabilities:
- lambda-janitor: cron job to delete old, unused versions of all Lambda functions in the region to free up storage space.
- auto-subscribe-log-group-to-arn: subscribes new and existing CloudWatch log groups to a Lambda function, Kinesis stream, or Firehose delivery stream by ARN.
- auto-set-log-group-retention: updates the retention policy for new and existing CloudWatch log groups to a specified number of days to reduce CloudWatch Logs cost.
- async-custom-metrics: lets you record custom metrics by writing to stdout (which is recorded in CloudWatch Logs) which is then parsed and forwarded to CloudWatch metrics as custom metrics.
- propagate-cfn-tags: propagates CloudFormation tags to resources that are not automatically tagged, e.g. CloudWatch log groups.
- autodeploy-layer: automatically deploys a Lambda layer to all new and existing functions in the region. Supports opt-in and opt-out via function tags.
The Serverless framework has also introduced Serverless Components. It is an alternative to SAR for building reusable and composable applications. But since it’s specific to the Serverless framework, you won’t be able to use it with Control Tower’s account factory. Because account factory relies on AWS Service Catalog and CloudFormation.
In summary, the rule of thumb is:
- If the capability is universal and should apply to all of your serverless projects, then build it into your platform.
- Otherwise, use a plugin to implement capabilities that are required at a project-by-project basis.
- Centralised logging for AWS Lambda
- Centralised logging for AWS Lambda, revisited (2018)
- Just how expensive is the full AWS-SDK?
- AWS re:Inforce 2019: Using AWS Control Tower to Govern Multi-Account AWS Environments (GRC313-R)
I specialise in rapidly transitioning teams to serverless and building production-ready services on AWS.
Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.
Check out my new course, Learn you some Lambda best practice for great good! In this course, you will learn best practices for working with AWS Lambda in terms of performance, cost, security, scalability, resilience and observability. Enrol now and enjoy a special preorder price of £9.99 (~$13).
Are you working with Serverless and looking for expert training to level-up your skills? Or are you looking for a solid foundation to start from? Look no further, register for my Production-Ready Serverless workshop to learn how to build production-grade Serverless applications!
Here is a complete list of all my posts on serverless and AWS Lambda. In the meantime, here are a few of my most popular blog posts.
- Lambda optimization tip – enable HTTP keep-alive
- You are thinking about serverless costs all wrong
- Many faced threats to Serverless security
- We can do better than percentile latencies
- I’m afraid you’re thinking about AWS Lambda cold starts all wrong
- Yubl’s road to Serverless
- AWS Lambda – should you have few monolithic functions or many single-purposed functions?
- AWS Lambda – compare coldstart time with different languages, memory and code sizes
- Guys, we’re doing pagination wrong