AWS Serverless Traps

Serverless: The Good

The Serverless concept is around now for quite some time and has received rightful praise for it’s ease of use, scalability and quick deployment. Even this blog runs Serverless, with the content stored on an S3 bucket and delivered via Cloudfront and Route53.

Many of my OSINT data collectors are rewritten to Serverless concepts and cost less than $5 per month. You can’t get a decent VPS for that kind of money and functionality it provides. I’m working on serverless solutions with security automation in mind mostly, and below are some of the challenges I found out about the hard way.

Serverless: The Bad

However, Serverless has some hidden traps to be aware off when deploying your production-ready applications.

Lambda concurrency
For example, the concurrency of your Lambda’s is by default unlimited. This can result in a higher bill than expected, if out of the blue thousands of requests are submitted. The concurrency trap can be avoided by setting a hard limit on how many concurrent Lambda’s can be executed at the same time. This might builds up a bigger queue, and that’s a trade off to think about. You can set the concurrency in the AWS template as shown in the snippet below:

  ExampleFunction:
    Type: AWS::Serverless::Function
    Properties:
      ReservedConcurrentExecutions: 5

Overprovisioning Lambda
Another trap can be overprovisioning of resources like RAM and CPU for the Lambda. Overprovisioning has cost me some bucks and to prevent this from happening again, I now deploy the application and then push like a thousand request that are similar to day-to-day load. With the data collected in Cloudwatch, you can use Insights that has fantastic example queries on how much resources your Lambda’s have been using. AWS has a blog post on this topic that details how to use the Lambda log data for this purpose as well.

You can set the Lambda size in your SAM template like this:

  ExampleFunction:
    Type: AWS::Serverless::Function
    Properties:
      MemorySize: 128

DynamoDB reserved read-write capacity
The last example I want to give is the r/w capacity of DynamoDB. In DynamoDB, you pay for reserved read and write capacity. This is useful when you know what your throughput capacity is but for most of the ad-hoc applications I’m running this is not required. What you can do instead is set the read/write capacity to ondemand. Now you only pay for what you use and even get some capacity in the free tier!

To configure your DynamoDB for ondemand capacity in your SAM template, see the snippet below:

  ExampleTable:
    Type: "AWS::DynamoDB::Table"
    Properties:
      BillingMode: PAY_PER_REQUEST

Closing remarks

As most of my scripts show, I’m utilizing Serverless a lot and for good reason! However, to help myself and others to not have an unexpected bill at the end of the month (trust me, I got a few scares) I wanted to capture my learnings. As more will pop up, this post will be updated.