# Load testing at scale > Aws lambda

# Distributed Load Testing on AWS Lambda

This guide describes Artillery’s support for running highly-distributed serverless load tests on AWS Lambda.

You’ll learn:

* How to scale out your Artillery tests using built-in AWS Lambda support
* What AWS resources Artillery creates on your behalf to run your tests
* Current limitations in AWS Lambda support in Artillery

## AWS credentials

To execute tests in AWS Lambda the Artillery CLI makes use of the official [AWS SDK](https://aws.amazon.com/tools/) to create the resources needed to run your tests (see the [AWS Resources](#aws-resources-created) section for details on what Artillery creates).

The SDK requires [AWS credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) to be present to work. Please refer to the official AWS documentation if you don't have one set up already: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html

Please see the [IAM Permissions](#iam-permissions) section for details on permissions required to run tests from AWS Lambda.

## Running tests from AWS Lambda

To run an existing test script from AWS Lambda, simply run an existing test using the `run-lambda` command.

For example, if you have a test script saved in `blitz.yml` and you want to run it from `eu-west-1` region, run the following command:

```sh
artillery run-lambda \
   --region eu-west-1 \
   blitz.yml
```

## How it works

### AWS resources created

Artillery will create a number of AWS resources behind the scenes to be able to execute your tests. All resources created by Artillery are **serverless** and created **on-demand**. There are no long-running infrastructure components involved.

* An **S3 bucket** to store an AWS Lambda deployment package generated from your test script
* An **AWS Lambda function**. This function is reused by tests using the same Artillery version.
* An **SQS queue** for communication between Lambda workers executing your test and the Artillery CLI. This queue is deleted once the test run completes.
* (Optional) An **IAM role** named **artilleryio-default-lambda-role** for Lambda functions running your test. This role uses the official AWS-managed [**AWSLambdaBasicExecutionRole** and **AWSLambdaVPCAccessExecutionRole**](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html#permissions-executionrole-features) policies, and an additional policy which grants access to the SQS queues created for these tests. If a role with that name already exists, Artillery will use it instead of creating it.

### IAM permissions

The AWS profile that the Artillery CLI runs under when you run `artillery run-lambda` needs to have sufficient permissions to be able to create the resources listed above. If running in a sandbox/developer account, the easiest way is to run with **admin** privileges using the default AWS [**AdministratorAccess**](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#jf_administrator) managed policy.

Example IAM policy definition to use instead of  \*\*AdministratorAccess\*\* Notes: Create an IAM Role with the following policy and attach it to the IAM user you're using to run Artillery tests. \`123456789000\`  will need to be replaced with the id of the AWS account you'll be using. \`\{
&#x20; "Version": "2012-10-17",
&#x20; "Statement": \[
&#x20;   \{
&#x20;     "Sid": "CreateOrGetLambdaRole",
&#x20;     "Effect": "Allow",
&#x20;     "Action": \[
&#x20;       "iam:CreateRole",
&#x20;       "iam:GetRole",
&#x20;       "iam:PassRole",
&#x20;       "iam:AttachRolePolicy"
&#x20;     ],
&#x20;     "Resource": "arn:aws:iam::123456789000:role/artilleryio-default-lambda-role-\*"
&#x20;   },
&#x20;   \{
&#x20;     "Sid": "CreateLambdaPolicy",
&#x20;     "Effect": "Allow",
&#x20;     "Action": \["iam:CreatePolicy"],
&#x20;     "Resource": "arn:aws:iam::123456789000:policy/artilleryio-lambda-policy-\*"
&#x20;   },
&#x20;   \{
&#x20;     "Sid": "SQSPermissions",
&#x20;     "Effect": "Allow",
&#x20;     "Action": \["sqs:\*"],
&#x20;     "Resource": "arn:aws:sqs:\*:123456789000:artilleryio\*"
&#x20;   },
&#x20;   \{
&#x20;     // ListQueues does cannot be scoped to individual resources
&#x20;     // https://docs.aws.amazon.com/service-authorization/latest/reference/list\_amazonsqs.html#amazonsqs-queue
&#x20;     "Sid": "SQSListQueues",
&#x20;     "Effect": "Allow",
&#x20;     "Action": \["sqs:ListQueues"],
&#x20;     "Resource": "\*"
&#x20;   },
&#x20;   \{
&#x20;     "Sid": "LambdaPermissions",
&#x20;     "Effect": "Allow",
&#x20;     "Action": \[
&#x20;       "lambda:InvokeFunction",
&#x20;       "lambda:CreateFunction",
&#x20;       "lambda:DeleteFunction",
&#x20;       "lambda:GetFunctionConfiguration"
&#x20;     ],
&#x20;     "Resource": "arn:aws:lambda:\*:123456789000:function:artilleryio-\*"
&#x20;   },
&#x20;   \{
&#x20;     "Sid": "EcrPullImagePermissions",
&#x20;     "Effect": "Allow",
&#x20;     "Action": \[
&#x20;       "ecr:GetDownloadUrlForLayer",
&#x20;       "ecr:BatchGetImage"
&#x20;     ],
&#x20;     "Resource": "arn:aws:ecr:\*:248481025674:repository/artillery-worker"
&#x20;   },
&#x20;   \{
&#x20;     "Sid": "S3Permissions",
&#x20;     "Effect": "Allow",
&#x20;     "Action": \[
&#x20;       "s3:CreateBucket",
&#x20;       "s3:DeleteObject",
&#x20;       "s3:GetObject",
&#x20;       "s3:PutObject",
&#x20;       "s3:ListBucket",
&#x20;       "s3:GetLifecycleConfiguration",
&#x20;       "s3:PutLifecycleConfiguration"
&#x20;     ],
&#x20;     "Resource": \[
&#x20;       "arn:aws:s3:::artilleryio-test-data-\*",
&#x20;       "arn:aws:s3:::artilleryio-test-data-\*/\*"
&#x20;     ]
&#x20;   }
&#x20; ]
}\`

#### Setting up the IAM Policy and Role in AWS

> **Info:** You do not need to set these up if you're running as **admin** using the default **AdministratorAccess** policy.

To help you get started, we've set up a [CloudFormation stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html) you can use to automatically provision the IAM role with required permissions. The stack will create:

* An IAM role named **ArtilleryDistributedTestingLambdaRole**
* An **ArtilleryDistributedTestingLambdaPolicy** (the policy definition outlined above) that will be attached to the role.

##### Create the IAM Permissions using the CloudFormation stack

[![Launch Stack](/img/launch-stack.svg)](https://console.aws.amazon.com/cloudformation/home#/stacks/create/review?templateURL=https://artilleryio-cf-templates.s3.amazonaws.com/aws-iam-lambda-cf-template.yml\&stackName=ArtilleryDistributedTestingLambdaIAMStack)

1. Click the **Launch Stack** button above to open the AWS CloudFormation **Quick create stack** page.
2. Adjust the **trust relationship** if needed:
   * By default, the role will trust your **AWS account**, meaning any [principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html#intro-structure-principal) from your account (e.g. IAM User, IAM Role) will be trusted to assume the role. If you would prefer to configure the role to trust only a **specific IAM user or role**, enter their name in the appropriate **User**/**Role** parameter field before creating the stack.
3. Click **Create stack**.
4. Once the stack is created, the **ArtilleryDistributedTestingLambdaRole** will be ready to use.

*Note: Ensure the AWS entity (e.g. IAM user) you are using has permission to assume the role you just created. This is necessary to run Artillery tests.*

(Alternative) Create the IAM Permissions manually If you would prefer to create the IAM role manually, you can follow the steps below: You should first create the policy. You can do that from the AWS UI or CLI. To do it from the UI: Go to  \*\*IAM\*\*  ->  \*\*Policies\*\*  and select  \*\*Create Policy\*\* . Select  \*\*JSON\*\* . Copy the example JSON policy definition from the section above. You’ll need to change the following: Change the AWS account from  \`123456789000\`  to your account ID; Remove any comments from the JSON policy, as that is not allowed; Press  \*\*Next\*\*  and give the policy a meaningful name. After the policy created, you'll need to use that policy in a role: Go to  \*\*IAM\*\*  ->  \*\*Roles\*\*  and select  \*\*Create Role\*\* ; Select  \*\*Custom Trust Policy\*\* : The trust policy of a role is used to define  principals  that you trust to assume the role (e.g. IAM user, IAM role, service). If you're using a specific IAM user when running Artillery tests, you can use the following trust policy: \`\{
&#x20; "Version": "2012-10-17",
&#x20; "Statement": \[
&#x20;   \{
&#x20;     "Effect": "Allow",
&#x20;     "Principal": \{
&#x20;       "AWS": "arn:aws:iam::123456789000:user/iam-user-name" // Replace the value with the ARN of your user
&#x20;     },
&#x20;     "Action": "sts:AssumeRole"
&#x20;   }
&#x20; ]
}\` If you are using a specific IAM role when running Artillery tests set the   \*\*AWS\*\*  in  \*\*Principal\*\*  to your  \*\*IAM role ARN\*\*  instead of the  \*\*user ARN\*\* . For more info about how to configure the trust policy, check out this  blog post  and the  AWS documentation . After, on the  \*\*Add Permissions\*\*  UI, select the policy created in the previous step; Finally, press  \*\*Next\*\*  and give the role a meaningful name. \*\*That's it!\*\*  You should now be able to use this role to run Artillery tests in Lambda. If you're setting up OIDC, for example to interact with GitHub Actions, then you might need to set a different Custom Trust Policy for the role created above (added in step 3).
Follow the  GH Actions guide  to get the appropriate Trust Policy.

## Limitations

* **Test Duration**: AWS Lambda is [limited to 15 minutes](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html#function-configuration-deployment-and-execution) of running time, which means that the entire load test cannot run for longer than 15 minutes at the moment.
* **A running test cannot be stopped**: Once a load test starts, it will run to completion. This is because once an AWS Lambda starts, there is no way to stop it (using the AWS SDK or AWS console). Be mindful of this, and ramp up load on your applications gradually.
* **Artillery features**:
  * `before` and `after` hooks run once in each Lambda worker rather than once per test run
  * `--target`, and `--insecure` flags for the `run` command are unavailable in Lambda tests

## Retention Settings

### `S3` Lifecycle Configuration

Objects created in Artillery's s3 bucket in your AWS account have the following lifecycle rules by default:

* Test Run artifacts: 2 days
* Test Run metadata: 7 days

## Questions?

* Post your questions on the community forum on GitHub at https://github.com/artilleryio/artillery/discussions
* Report a bug or raise an issue via https://github.com/artilleryio/artillery/issues
