AWS Lambda in Action. Part 2: getting to know development and testing tools



This guide is the result of personal experience in developing and testing Serverless applications, as well as maneuvering between crutches and bicycles when trying to test them. When I first started developing Serverless applications, I had to figure everything out with my hands, there were no clear guides or convenient tools for local development and testing.

Now the situation is changing: tools began to appear, but finding manuals on their use is not easy. In this article I will show with a simple example how to work with the new functionality. You can easily master it and get around those problems and bugs that I was “lucky” to encounter.

You will learn how to develop using the AWS, SAM-CLI, and IntelljIDEA browser console. I’ll also talk about testing: integration, E2E and unit tests. And finally, we will discuss how much such a solution will cost (spoiler: you can save a lot on it).

This article will be useful to those who begin to develop Serverless applications and are not yet familiar with its tools and approaches.


What will be discussed


Hello everyone! My name is Alexander Gruzdev, and I am pleased to present the second part of the article about the use and development of Serverless-solutions based on AWS Lambda. In the sequel, we’ll talk about the ways of developing and testing the solution from the first part ( AWS Lambda in Action in Java 11. We visit Serverless in “Production” ).

Since the publication of the last article, the test application has been slightly revised, but the main meaning remains the same. This is a trivial HTML form “Contact Us”, which sends data from the form to the Gateway API through HTTP requests, and it, in turn, proxies the processing request to AWS Lambda. During processing, the lambda writes data to the DynamoDB table and sends a letter through AWS SES. The component diagram is presented below.

Components diagram


Content


  1. Development Using the AWS Browser Console
  2. Development using SAM-CLI
  3. Development using IntelljIDEA
  4. Types of Testing
  5. Serverless Costs
  6. useful links



1. Development using the AWS browser console



AWS Console


The AWS console provides access to any AWS service, be it your EC2 virtual server, IAM or AWS Lambda role / access policy settings with all parameters that can be changed in real time without redeployment through Continuous Delivery / Continuous Deployment systems.

This greatly speeds up the development process and some types of testing. It also helps to visually control the launch and operation parameters of your applications.

API Gateway Console


The console allows you to monitor the current state of the application, manage your environments and deliver new versions. I will show how this can be used to verify the health of the environment.

Let's see what this “magic” console looks like in the screenshot of the Resources tab of the Contact Us application: The screenshot shows how the request from the client through the Gateway API gets into the lambda and how the response will be returned back to the client when the / contact resource is called by the POST method.

Gateway resources



  • Method request - the first step in processing the request. In our case, it does not contain any settings, but may contain, for example, settings for authorization.
  • Integration request means that the HTTP request will be transmitted to the lambda in a special format: it contains all the information sent by the client and details about the called context.
  • Integration response says that the HTTP client will receive the response directly from the lambda. Therefore, you yourself are responsible for the formation of the response body in lambda.


Disable proxy integration
API Gateway , Use Lambda Proxy integration Integration Request. . , , .


Integration request sample
SAM init events, , Integration request. , AWS , . AWS Lambda.


Press the TEST button to verify the application is working. This will give you access to the HTTP Gateway API calls.

In the following screenshot, I sent a request to warm up the lambda: In addition to responding to the request, the Gateway API displays detailed logs. In the same way, you can make a real request by substituting the JSON request body in the form:
Gateway test request


{
    "subject": "Email subject",
    "question": "Your question…",
    "username": "Your name…",
    "phone": "Your phone…",
    "email": "Your email…"
} 


So you can manually test your API without any UI forms and Front-end applications, thereby separating front-end and back-end development. As an alternative to the built-in console, you can use Postman or any other HTTP client.

Postman as an alternative
HTTP- Postman. . , API Gateway AWS , API. , , AWS .


Lambda Console


For testing and development, in addition to requests through the Gateway API, you can use the AWS Lambda browser console.

Its screen is divided into several blocks:
  • Designer shows existing triggers and layers. In our case, the trigger is API Gateway. If we click on it, all the necessary information will open: URL, stage, resource path.
  • Aliases (available when selecting a specific lambda alias) allows you to configure the distribution of traffic by version of lambda. More on this in the next paragraph.
  • Function code — . zip- , . , Function code . Python/NodeJs.
  • Environment variables. , . , , . , . , , .
  • Tags — , , , , .
  • Execution role — ( ) , .
  • Basic settings — .
  • Network: - , VPC. — .
  • AWS X-Ray . AWS-.
  • Reserve concurrency , . .
    Provisioned concurrency
  • Provisioned concurrency — . , . , — . Free Tier .
  • Asynchronous invocation allows you to configure special handling of asynchronous requests. We indicate how many repeated calls to make in case of an error, and for how long the request can hang in the queue. Optionally, you can specify a queue for processing requests that fail.

  • Database proxies is another new feature that allows you to configure access to the database through proxies in the form of API Gateway + Lambda.


Next, let's see how to develop from this console. In addition to changing the parameters, the Configure Test Events functionality can be used to create a test request. A rather extensive list is available, but we will take advantage of what I have already attached in the project:
ContactUs request
{
  "body": "{\"subject\": \"Question\",\"question\": \"How much does it cost\",\"username\": \"Alex\",\"phone\": \"+79999999999\",\"email\": \"alex@gmail.com\"}",
  "resource": "/{proxy+}",
  "path": "/path/to/resource",
  "httpMethod": "POST",
  "isBase64Encoded": false,
  "queryStringParameters": {
    "foo": "bar"
  },
  "pathParameters": {
    "proxy": "/path/to/resource"
  },
  "stageVariables": {
    "baz": "qux"
  },
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, sdch",
    "Accept-Language": "en-US,en;q=0.8",
    "Cache-Control": "max-age=0",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-Country": "US",
    "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Custom User Agent String",
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "123456",
    "stage": "prod",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "requestTime": "09/Apr/2015:12:34:56 +0000",
    "requestTimeEpoch": 1428582896000,
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "accessKey": null,
      "sourceIp": "127.0.0.1",
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Custom User Agent String",
      "user": null
    },
    "path": "/prod/path/to/resource",
    "resourcePath": "/{proxy+}",
    "httpMethod": "POST",
    "apiId": "1234567890",
    "protocol": "HTTP/1.1"
  }
}


After adding the request, click Test and see the result of the lambda: Lambda returns JSON, which contains the status code and response body. The body value will go directly to the client that called the Gateway API. In addition, the screenshot has the characteristics of the call: the execution time, the execution time for which we will pay, the maximum amount of memory that was consumed by the lambda. Relying on these metrics, we can configure the optimal amount of memory so that the lambda matches your price / response rate requirements.
Gateway resources



Using the AWS Console to Test Canary Deployment


Now let's touch on one important point related to the deployment of a new version of lambda. I specified such parameters when I wrote the SAM template:
AutoPublishAlias: live
DeploymentPreference:
  Type: Canary10Percent10Minutes

The first parameter automatically adds an alias live to each new version of the lambda .
A bit about aliases
, . , , API Gateway. 1, 2, 3 . LATEST, . 2 3 API Gateway (Stage AWS), Gateway-Lambda. API Gateway (ARN ), LATEST.

— ( ), , , ARN . , Stage API Gateway . , API Gateway: dev, qa prod .

, , . , . , live, . live- , , , , CloudWatch.


To test canary deployment, you can use both the Gateway API console and the Lambda console.

First you need to change the lambda code so that it returns a different answer. For example, in the warm-up processing, specify Version 2 instead of Version 1 in the response. This will be our marker.

Now, using the API functionality of the Gateway Test, we can make sure that within ten minutes when sending WARM-UP requests, only 10% of the responses will have Version 2 in the response body. After this time, Version 2 will return 100% of the requests.

In addition to the Gateway API console, we can use the Lambda console, where, having selected the necessary alias, we see a traffic distribution policy that can be controlled.
Lambda alias



2. Local development using SAM-CLI


Some time ago, one of the main disadvantages of using lambda was considered inconvenience in the development and testing on the local machine. Now the situation has changed a lot: SAM-framework has appeared, which allows not only to collect and deploy solutions, but also simplifies local development.

For example, you can call your lambda directly from the console:
sam local invoke -e ./events/warm_up_request.json ContactUsFunction

This command is launched from the directory with the SAM template and transfers the contents of the JSON file to the input lambda ContactUsFunction (this is the logical name in the template).

That is, using this command, SAM raises the image lambci / lambda: java11 in docker , and runs your code in it. To access remote services, such as SES, your AWS configuration with a secret / access key is used, so it must be up to date. Another important point: if you do not add a header for the warm-up mode, the real AWS SES and DynamoDB services will be called.

Call log here
F:\aws\projects\contact-us-sam-app>sam local invoke -e ./events/warm_up_request.json ContactUsFunction
Invoking com.gralll.sam.App::handleRequest (java11)
Fetching lambci/lambda:java11 Docker container image......
Mounting F:\aws\projects\contact-us-sam-app\.aws-sam\build\ContactUsFunction as /var/task:ro,delegated inside runtime container
?[32mSTART RequestId: a86d65fa-1f19-15c5-93b8-d87631c80ee2 Version: $LATEST?[0m
2020-01-06 19:09:17 a86d65fa-1f19-15c5-93b8-d87631c80ee2 INFO  App - Request was received
2020-01-06 19:09:17 a86d65fa-1f19-15c5-93b8-d87631c80ee2 DEBUG App - {
  "body" : "{\"subject\": \"Question\",\"question\": \"How much does it cost\",\"username\": \"Alex\",\"phone\": \"+79999999999\",\"email\": \"alex@gmail.com\"}",
  "resource" : "/{proxy+}",
  "requestContext" : {
    "resourceId" : "123456",
    "apiId" : "1234567890",
    "resourcePath" : "/{proxy+}",
    "httpMethod" : "POST",
    "requestId" : "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "extendedRequestId" : null,
    "accountId" : "123456789012",
    "identity" : {
      "apiKey" : null,
      "apiKeyId" : null,
      "userArn" : null,
      "cognitoAuthenticationType" : null,
      "caller" : null,
      "userAgent" : "Custom User Agent String",
      "user" : null,
      "cognitoIdentityPoolId" : null,
      "cognitoIdentityId" : null,
      "cognitoAuthenticationProvider" : null,
      "sourceIp" : "127.0.0.1",
      "accountId" : null,
      "accessKey" : null
    },
    "authorizer" : null,
    "stage" : "prod",
    "path" : "/prod/path/to/resource",
    "protocol" : "HTTP/1.1",
    "requestTime" : "09/Apr/2015:12:34:56 +0000",
    "requestTimeEpoch" : 1428582896000,
    "elb" : null
  },
  "multiValueQueryStringParameters" : { },
  "multiValueHeaders" : {
    "X-WARM-UP" : [ "13" ]
  },
  "pathParameters" : {
    "proxy" : "/path/to/resource"
  },
  "httpMethod" : "POST",
  "stageVariables" : {
    "baz" : "qux"
  },
  "path" : "/path/to/resource",
  "isBase64Encoded" : false,
  "requestSource" : "API_GATEWAY"
}
2020-01-06 19:09:17 a86d65fa-1f19-15c5-93b8-d87631c80ee2 INFO  App - Lambda was warmed up
?[32mEND RequestId: a86d65fa-1f19-15c5-93b8-d87631c80ee2?[0m
?[32mREPORT RequestId: a86d65fa-1f19-15c5-93b8-d87631c80ee2     Init Duration: 1984.55 ms       Duration: 42.22 ms      Billed Duration: 100 ms Memory Size: 256 MB     Max Memory Used: 102 MB ?[0m
{"statusCode":201,"multiValueHeaders":{"Access-Control-Allow-Origin":["*"]},"body":{"response":"Lambda was warmed up. V1"},"isBase64Encoded":false}


In addition to the lambda log, service information on the call status and a response in JSON format are written to the console.

The Gateway API, like the lambda, can be run locally.
We execute the command:
sam local start-api

Console log at startup
F:\aws\projects\contact-us-sam-app>sam local start-api
Mounting ContactUsFunction at http://127.0.0.1:3000/contact [POST, OPTIONS]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2020-01-06 22:20:30  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)


After starting the server, we can execute requests. I will use Postman and send a request to warm up the lambda.

In the console we see
Invoking com.gralll.sam.App::handleRequest (java11)
Fetching lambci/lambda:java11 Docker container image......
Mounting F:\aws\projects\contact-us-sam-app\.aws-sam\build\ContactUsFunction as /var/task:ro,delegated inside runtime container
?[32mSTART RequestId: 27868750-3637-1f80-3d80-53a724da16ef Version: $LATEST?[0m
2020-01-06 19:28:09 27868750-3637-1f80-3d80-53a724da16ef INFO  App - Request was received
2020-01-06 19:28:09 27868750-3637-1f80-3d80-53a724da16ef DEBUG App - {
  "body" : "{\r\n  \"subject\": \"Question\",\r\n  \"question\": \"How much does it cost\",\r\n  \"username\": \"Alex\",\r\n  \"phone\": \"+79999999999\",\r\n  \"email\": \"alex@gmail.com\"\r\n}",
  "resource" : "/contact",
  "requestContext" : {
    "resourceId" : "123456",
    "apiId" : "1234567890",
    "resourcePath" : "/contact",
    "httpMethod" : "POST",
    "requestId" : "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "extendedRequestId" : null,
    "accountId" : "123456789012",
    "identity" : {
      "apiKey" : null,
      "apiKeyId" : null,
      "userArn" : null,
      "cognitoAuthenticationType" : null,
      "caller" : null,
      "userAgent" : "Custom User Agent String",
      "user" : null,
      "cognitoIdentityPoolId" : null,
      "cognitoIdentityId" : null,
      "cognitoAuthenticationProvider" : null,
      "sourceIp" : "127.0.0.1",
      "accountId" : null,
      "accessKey" : null
    },
    "authorizer" : null,
    "stage" : "Prod",
    "path" : "/contact",
    "protocol" : null,
    "requestTime" : null,
    "requestTimeEpoch" : 0,
    "elb" : null
  },
  "multiValueQueryStringParameters" : null,
  "multiValueHeaders" : {
    "Accept" : [ "application/json" ],
    "Accept-Encoding" : [ "gzip, deflate, br" ],
    "Accept-Language" : [ "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7" ],
    "Cache-Control" : [ "no-cache" ],
    "Connection" : [ "keep-alive" ],
    "Content-Length" : [ "150" ],
    "Content-Type" : [ "text/plain;charset=UTF-8" ],
    "Host" : [ "127.0.0.1:3000" ],
    "Origin" : [ "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop" ],
    "Postman-Token" : [ "5cadaccd-6fae-5bc2-b4ef-63900a1725ff" ],
    "Sec-Fetch-Mode" : [ "cors" ],
    "Sec-Fetch-Site" : [ "cross-site" ],
    "User-Agent" : [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" ],
    "X-Forwarded-Port" : [ "3000" ],
    "X-Forwarded-Proto" : [ "http" ],
    "X-Warm-Up" : [ "123" ]
  },
  "pathParameters" : null,
  "httpMethod" : "POST",
  "stageVariables" : null,
  "path" : "/contact",
  "isBase64Encoded" : false,
  "requestSource" : "API_GATEWAY"
}
2020-01-06 19:28:09 27868750-3637-1f80-3d80-53a724da16ef INFO  App - Lambda was warmed up
?[32mEND RequestId: 27868750-3637-1f80-3d80-53a724da16ef?[0m
?[32mREPORT RequestId: 27868750-3637-1f80-3d80-53a724da16ef     Init Duration: 1951.87 ms       Duration: 42.91 ms      Billed Duration: 100 ms Memory Size: 256 MB     Max Memory Used: 102 MB ?[0m
2020-01-06 22:28:11 127.0.0.1 - - [06/Jan/2020 22:28:11] "POST /contact HTTP/1.1" 201 -


Logs, of course, are not formatted in the best way. Hopefully this will be fixed in the future.

Important: when changing the lambda code, restarting the API is not necessary. It is enough to rebuild the lambda with the sam build command .
A bit about bugs
Java- aws-serverless-java-container-core, : 502 . :
Invalid API Gateway Response Keys: {'base64Encoded'} in {'statusCode': 200, 'headers': {'Content-Type': 'text/plain'}, 'body': 'Hello World', 'base64Encoded': False} 

- , API Gateway AWS JsonProperty. 'isBase64Encoded' 'base64Encoded', , , . , Java- ContactUsProxyResponse AwsProxyRequest.



3. Local calls from IDEA


Everything described in the paragraph above is the functionality of the SAM tool. It is controlled from the command line and can be integrated into any interface. This is exactly what was done in the plugin for IntelljIDEA AWS Toolkit.

This plugin adds additional configurations for launching a lambda straight from the IDE. This is what the configuration window looks like. You must either select a template with a description of the lambda, or configure the settings manually. In the first case, the amount of memory and language for compilation will be automatically taken from the template. In the second case, you can configure the amount of RAM yourself and make an approximate calculation of the limit. Another plugin allows you to run the configuration directly from the window of the Java code editor or yaml-template. Screenshots below:











That, in fact, is all. By running the customized configuration, you simply automate frequent lambda calls from the console. Agree, quite comfortable?


4. Testing


Here we talk about the types of tests for lambdas. Since I used Java in the example, the tests will also include fairly standard tools for unit and integration testing: Junit 4, Mockito and PowerMockito.

Unit tests


To cover the lambda code with unit tests, you do not need to have specific knowledge. It is enough to apply standard Java practices: lock all the dependencies in the class and try to test all possible cases of request processing.

I did not add all the test scenarios and limited myself to two positive and two negative scenarios.

The first positive test verifies that if there is an X-WARM-UP header, there are no requests in DbService and EmailService. The second case checks that these services will be called if the request is real. These are the simplest tests, and I omitted part of the checks in them.

Negative scenarios are a response check in case of a client or server processing error.

Integration tests


As for integration tests, I decided to check out DbService and its work with the DynamoDB table.

In this case, I used the Localstack tool . This solution provides free mokas for AWS services that run as docker containers.

To install this solution, just run the commands:
pip install localstack
localstack start

Or you can use the docker-compose file .
docker-compose for raising only DynamoDB
version: '2.1'
services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
    image: localstack/localstack
    ports:
      - "4567-4599:4567-4599"
      - "${PORT_WEB_UI-8080}:${PORT_WEB_UI-8080}"
    environment:
      - SERVICES=dynamodb
      - DEBUG=${DEBUG- }
      - DATA_DIR=${DATA_DIR- }
      - PORT_WEB_UI=${PORT_WEB_UI- }
      - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR- }
      - KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- }
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - "${TMPDIR:-/tmp/localstack}:/tmp/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"


The start command raises all available AWS services by default. To raise DynamoDB specifically, just set the environment variable:
set SERVICES=dynamodb


There is a special LocalstackTestRunner for Junit that allows you to start the necessary services using the @LocalstackDockerProperties configuration .
As a result, writing a test for DbService looks like this:
  • Add over the test class.
    @RunWith(LocalstackTestRunner.class)
    @LocalstackDockerProperties(services = { "dynamodb" })
    

  • Create a table
    java
    @Before
    public void setUp() {
        AmazonDynamoDB clientDynamoDB = TestUtils.getClientDynamoDB();
        dynamoDB = new DynamoDB(clientDynamoDB);
        dbService = new DbService(dynamoDB);
    
        dynamoDB.createTable(
                new CreateTableRequest()
                        .withTableName("ContactUsTable")
                        .withKeySchema(new KeySchemaElement("Id", KeyType.HASH))
                        .withAttributeDefinitions(new AttributeDefinition("Id", ScalarAttributeType.S))
                        .withProvisionedThroughput(new ProvisionedThroughput(10L, 10L)));
    }
                    


  • We describe the test scenario
    java
    // given
    ContactUsRequest contactUsRequest = new ContactUsRequest("subject", "name", "+79991234545", "123@mail.ru", "Qeustion");
    
    // when
    dbService.putContactUsRequest("123", contactUsRequest);
    
    // then
    Item item = dynamoDB.getTable("ContactUsTable").getItem(new PrimaryKey("Id", "123"));
    assertEquals(contactUsRequest.getSubject(), item.get("Subject"));
    assertEquals(contactUsRequest.getUsername(), item.get("Username"));
    assertEquals(contactUsRequest.getPhone(), item.get("Phone"));
    assertEquals(contactUsRequest.getEmail(), item.get("Email"));
    assertEquals(contactUsRequest.getQuestion(), item.get("Question"));
                  


  • Do not forget to delete the table after the test.
    java
    @After
    public void tearDown() {
        dynamoDB.getTable("ContactUsTable").delete();
    }
                   



As a result, using Localstack, we get a fairly extensive range of AWS mocks that allow you to emulate the work of these services.

E2E tests


To play E2E scenarios, it is better to raise AWS test services specifically for running tests, if, of course, there is such an opportunity. This can be done using the optional CloudFormation template, in which the resources will be copies of the main template.

The test can be done by calling the lambda through AWS-CLI and processing the result with any available tool. You can still make a call in unit tests, but without creating mobs.

Performance tests


Since performance testing deserves a separate article or even a book, I will not try to put all the information here. In short, when talking about stress testing, you need to remember that using almost all AWS services is not free, and you should be prepared to estimate the possible costs in advance.

If you want to evaluate the necessary resources for a lambda, use the UI console and make some test calls. Next, using commonplace logic and mathematics, evaluate how much your lambda’s performance increases depending on the amount of available resources.

Do not forget about CloudWatch. With its help, you can build quite indicative dashboards and based on them determine what parameters of lambda and spending you can afford.


5. The cost of serverless solutions


Evaluation of a solution is always specific, because you need to consider not only the cost of one call, but also incoming / outgoing traffic, the cost of caching, logging and monitoring. If you are considering using lambda, try to predict the load that your service will handle.

If these are single calls or an ETL process that runs every few hours / days, then the lambda is more likely to pay off. If you predict a load of several queries per second, be sure to make an accurate estimate.

Below I give approximate estimates of the cost of the lambda and the cheapest EC2 server, so that you understand what values ​​are in question: The following parameters for the lambda were taken to calculate:




  • Lead time: 150 milliseconds
  • Price: $ 0.00001667 for 1GB-s
  • Memory: 256 MB

For EC2 t2.nano:

  • Price: $ 4.75 per month
  • Memory: 512 MB
  • vCPU: 1
  • Maximum load: 5% CPU per month

I took EC2 load data from here . According to these calculations, the specified server can withstand a constant load of 0.3 requests per second. As the load increases, the response time will increase, which will reduce the efficiency of this server.

All these calculations are quite abstract and do not take into account many factors: prepayment discounts or a large number of requests, lambda execution time, and so on. But they show that with a load of less than 1 request per second, lambda costs less than the cheapest EC2 server.

By the way, do not forget to add the price of ALB to the EC2 price if you need to keep several application replicas or elastic IPs.


Testing and local development of Serverless solutions are less popular than the same microservices. Nevertheless, more and more people study and apply these technologies and give a chance to various open-source products to become better and more efficient. Such solutions greatly simplify the life of companies that need to release a product as soon as possible and not have to configure the entire infrastructure. But even in already developed products, I think there is a place for serverless databases or lambdas.

I do not claim to be an expert in the field of testing Serverless-solutions, but, based on my personal positive experience, I decided to highlight the main points in this article. I hope that they will be useful to someone, and perhaps some of you can supplement or even correct me, which I will be very happy about.


useful links



All Articles