Running faast.js on AWS Lambda
Setup
To use faast.js with AWS, you need to create an account and credentials for an IAM user. To setup credentials for AWS:
- If you haven't already, set up the AWS CLI:
$ pip install awscli --upgrade --user
- Create an IAM user in the AWS console.
- Setup an access key ID and secret access key for the IAM user.
- Add these credentials to your local machine with aws cli (
aws configure
). - Ensure AWS user has AdministratorAccess role and Administrator group.
That's it. Now you should be able to run faast.js with AWS Lambda.
faastAws
Using The faastAws
function allows you to specify more specific AwsOptions
than the more generic faast
function.
A common reason to use faastAws
is to specify the region:
faastAws(m, "/path", { region: "us-east-1" });
AWS Resources
The following diagram shows the AWS resources that faast.js creates:
In the cleanup
function the SNS topic, SQS queue, S3 Bucket, and Lambda function are deleted. Lambda Layers are retained for 24 hours, then removed by the next faast.js instance that runs garbage collection. The Lambda Role remains permanently.
All faast.js AWS resources can be removed using the faastjs cleanup command.
Logs
To view logs, see logUrl
.
AWS requires a new Cloudwatch log group to be created for each lambda function. So you're likely to see many log groups created when using faast.js. These log groups have their log streams expire automatically after 24h, and empty log groups are removed by garbage collection the next time faast.js garbage collection runs.
Log ingestion is not included in faast.js cost estimates.
Package Dependencies
By default, AWS does not provide a package dependency solution. Faast.js adds dependency bundling automatically using two different methods: webpack bundling and remote npm install.
Webpack bundling happens by default. When you specify a module to the faast
or faastAws
function, the module and its dependencies are collected by webpack and bundled into a single .js
file. This placed into a zipfile and sent to AWS Lambda as the code package. If you install dependencies using package.json
and import
or require
them in the usual way, then webpack should be able to bundle your dependencies with no extra effort on your part.
There are a few drawbacks with the default webpack approach. The first drawback is that the code bundle needs to be uploaded every time you invoke faast
because it creates fresh infrastructure each time it initializes. If the bundle is large, this can take a substantial amount of time. Worse, AWS limits code package sizes using direct upload to 50MB. The second drawback is that native dependencies are not supported in this way because webpack cannot bundle them.
To solve these issues, faast.js has the packageJson
option. Dependencies that are not specified in packageJson
will still be bundled as usual by webpack. For dependencies that are specified in packageJson
, faast.js will install the dependencies using a separately created Lambda function and save them in a cached Lambda Layer. In this way, native dependencies can be used. Using this method also increases the total code size maximum to 250MB (unzipped).
A good way to setup dependencies is therefore the following:
If you don't need native dependencies and your code size does not exceed 50MB, you don't need to specify dependencies explicitly and you don't need to use the
packageJson
option.If you do need
packageJson
, then ensure that the dependencies specified in it are a subset of the dependencies in your project'spackage.json
file. The dependencies should also have the same version constraints. The reason this is necessary is because the code you write locally is typed against the locally installed package, but the remote code will use the version specified inpackageJson
. The goal of this rule is to ensure that these versions are identical.It is possible to specify your project's
package.json
file as thepackageJson
option. The main drawback of this is that there may be a large number of dependencies in the project not needed for the remote faast functions, and the dependencies may be too large in aggregate.
To inspect what the bundled code package looks like, see FAAST_PACKAGE_DIR
.
Queue vs Https mode
There are two modes of invocation for AWS with faast.js, https and queue. In AWS, queue mode uses SNS to invoke lambda, whereas https mode uses a direct Lambda API invocation (however, return values are always returned via an SQS queue, and are bound by SQS message size limits). Here's how these compare on AWS:
https mode | queue mode | |
---|---|---|
latency | low | higher |
maximum argument size | 6MB | 256kb |
maximum return value size | 256kb | 256kb |
max invocations / sec | ~300/sec | > 600/sec |
In https mode, a socket connection is used for each invocation. This may encounter client-side limitations within configuration of a container or operating system. For more robust handling of higher concurrency levels, use queue mode, which avoids the use of large number of connections by routing requests and responses through AWS SQS.
The default is https mode.
IAM Roles
Faast.js will create an IAM role faast-cached-lambda-role
for the lambda function it creates. By default this role will have administrator access. The role will be created dynamically and will remain in your account cached even after cleanup function is called.
If you remove this role, it will be created again the next time faast.js runs.
Support for ARM with Graviton2
AWS Graviton2 is a new version of AWS Lambda that supports ARM (see this blog post for more details:). To use Graviton2:
const faastModule = await faastAws(funcs, {
awsLambdaOptions: {
Architectures: ["arm64"]
}
});