# Lambda

Lambda is AWS's offering for serverless computing (aka Functions as a Service, FaaS). It was the first public offering of such a service and the adoption kept rising since then. It is the simplest way to run your code.

AWS does a pretty good job with its documentation and the lambda section is no exception. Check it out here (opens new window).

# Design Considerations

The easiest way to work with lambda is to consider functions as event handlers. You don't build an app with a set of features - you build a set of functions that respond to certain events (e.g. a client requests a certain resource, a file was uploaded, the user registered).

So theoretically, all you have to do is choose a language from the supported ones (opens new window), write your event handler, decide how much RAM (opens new window) (CPU is proportional to RAM) to allocate to it and deploy it (opens new window). Of course, your code should be designed to work in such an environment mainly by making sure it is stateless. There is really no control over how the code is executed (e.g. is a function instance reused or not) so you shouldn't make any assumptions (like storing temporary files).

Besides making your functions stateless, it should also be idempotent. This means that if, for some reason, your function is executed multiple times for the same event/input, the state of the system (data) should be the same. This need comes from the fact that certain triggers have a chance of firing twice (usually queue-based triggers) and that lambda will retry in case the execution failure. The usual way of making a function idempotent is by adding a request ID and checking whether it was already processed - see here (opens new window).

Another important consideration is the unit of deployment. If, in the case of the other approaches (EC2, ECS/Fargate, Elastic Beanstalk) you deploy the entire application, with Lambda you deploy one function. Of course, it's up to you how much responsibility your function has. You can squeeze in an entire RESTful service or you can deploy the code responsible for one operation of the service within a function. We recommend the latter: this is what lambda was designed for and its limits (opens new window) clearly show it. A potentially important consideration for this approach is the cold start (opens new window).

And finally, the horizontal scaling capabilities of lambda can be a double-edged sword. Being able to handle all requests is great, but will the downstream resources be able to accept all those parallel streams of data? Probably the most common issue is running out of connections to RDS. For this, AWS came up with RDS Proxy (opens new window).

# Triggers

The most common triggers include:

  • API Gateway (or even Application Load Balancer) which forwards requests to lambda (lambda acts as a backend). Additionally, you can integrate API Gateway with Lambda to handle access control (opens new window) (i.e. check the identity and permission of the request).
  • S3 - do something when a file is uploaded (e.g. optimize an image - be careful when uploading the image back; you don't want to run in an infinite loop).
  • DynamoDB (DynamoDB Streams actually) - this can be especially helpful for NoSQL databases since we might need to handle duplicate data (e.g. if the product's name changes, we might need to update that in all open orders).
  • SDK - we can invoke Lambda functions from any program using the AWS SDK. People even use this to bypass the need of API Gateway - example here (opens new window).

The full list can be found here (opens new window).

# Useful Lambda Features

  • Aliases

We can minimize the impact of a breaking change and make sure that our system is always available by leveraging aliases (opens new window). They basically point to different co-existent versions of a function allowing you to shift traffic (gradually) between them.

  • Layers

Usually, you would deploy your entire application, with all its dependencies, bundled in a zip file. You can leverage lambda layers to store dependencies separately.

  • Lambda in VPC

You can deploy lambda in a VPC if you need it to interact with certain resources such as an RDS instance deployed in a private subnet. The function will be able to access the internet through a NAT Gateway (even for public subnets).

  • Destinations

You can configure lambda to send results to a destination (other lambda functions, SQS queue, SNS topic, or EventBridge bus). See more here (opens new window). This feature supersedes dead-letter queues.

  • Environmental Variables

You can define environmental variables which can be accessed through the usual way (e.g. process.env for Node.js functions). They can be encrypted and are defined per function version.