This chapter covers
If there’s one thing you take away from this book, it should be an understanding that a compute service such as Lambda is the heart of serverless architecture. You used Lambda in chapters 3 and 5, so you have a feel for it already. This chapter explores Lambda in more detail. It looks at core concepts and investigates design of functions. We explain features such as versioning and aliases and go over important design patterns such as async waterfall. We also continue to add features to 24Hour Video as we turn it into a full-fledged application.
Serverless compute services like Lambda are as big a shift for cloud computing as S3 was for cloud storage. If you think about it, the two are similar. S3 deals in objects for storage. You provide an object and S3 stores it. You don’t know how, you don’t know where, and you don’t really care. There are no drives to concern yourself with and no such thing as disk space. You can’t over-provision or under-provision storage capacity in S3.
Likewise, with Lambda you provide function code; Lambda executes it on demand. You don’t know how and you don’t know where. There are no virtual machines to concern yourself with, and there are no such things as server farm capacity, too many idling servers, not enough servers to meet demand, or scaling groups. You can’t over-provision or under-provision execution capacity in Lambda. It’s just what you want it to be and Amazon charges you only for the time it executes. This is why Lambda and similar serverless compute services such as Azure Functions, Google Cloud Functions, and IBM OpenWhisk are as big a shift forward for compute as S3 was for storage (http://bit.ly/2jQnlGB).
Some people prefer to use the acronym FaaS (function as a service) to describe technologies like Lambda. In fact, they prefer not to use the term serverless at all. They feel that it’s not accurate enough and that it needs to be constantly explained. In this book, we’ve been using the term serverless not as a synonym for Lambda but as a descriptor for an approach that encourages you to use a compute service, use third-party services and APIs, and employ powerful patterns and architectures (such as having thick front ends that talk directly to services using delegation tokens). Therefore, we say that serverless is an umbrella term that encompasses FaaS and that FaaS is just one aspect (albeit a very important one) of what serverless technologies and architectures have to offer.
Lambda is a serverless compute service that can execute code in response to the following:
Lambda functions can also run on a schedule, which makes them suitable for repeatable tasks such as backups or system health checks. Lambda supports functions written in four languages: JavaScript (Node.js), Python, C#, and Java. You’ve been using JavaScript so far, but there’s no reason why you couldn’t use one of the other languages. They’re all first-class citizens.
Lambda supports two invocation types: Event and RequestResponse.
Event invocation takes place when an event (such as a file being created in S3) triggers a Lambda function. You saw event invocations in chapter 3 when you used S3 and SNS to invoke Lambda. Event invocation is asynchronous. A Lambda function that executes because of an event doesn’t send a response back to the event source.
The other model is RequestResponse. It comes into play when Lambda is used with the API Gateway, invoked via the AWS console, or called with the CLI. Request-Response forces Lambda to execute the function synchronously and return the response to the caller. You used RequestResponse in chapter 5 when you integrated the API Gateway with the user-profile Lambda function. Note that if you invoke a function via the SDK/CLI, you can choose whether to use Event or RequestResponse invocation.
Lambda’s event-based invocation is quite interesting. It has two modes: push and pull. In a push model, a service (such as S3) publishes its event to Lambda and directly invokes your function. Figure 6.1 shows what this looks like.
In a pull model, Lambda’s runtime polls a streaming event source (such as a DynamoDB stream or a Kinesis stream) and invokes your function when needed. Figure 6.2 shows what this looks like.
In both models, an event source mapping describes how an event source is associated with a Lambda function. One subtle difference between push and pull is this: “With the pull model, you maintain the mappings in AWS Lambda by creating event source mappings using the relevant AWS Lambda API. With the push model, the event sources maintain the mapping and you use the APIs provided by the event sources to maintain the mapping” (http://amzn.to/1Xb78FV).
AWS has a cap of 100 concurrent executions across all functions within a region (per account). This cap, however, can be lifted by asking Amazon. The company says that the limit is there to protect developers “from costs due to potential runaway or recursive functions during initial development and testing” (http://amzn.to/29nORER). The number of concurrent executions is calculated differently depending on whether the event source is stream-based (that is, if the event source is Kinesis Streams or a DynamoDB stream) or not.
In a stream-based event source, function invocation concurrency is equal to the number of active shards. If, for example, there are 10 shards, there will be 10 Lambda functions executing concurrently. Lambda functions process records off shards in the order in which they arrive. If a function encounters an error processing a record, it retries until it succeeds or the record expires, before going on to the next one.
Amazon proposes a simple formula for estimating the number of concurrent invocations for non-stream event sources:
events (or requests) per second x function duration
A simple example is an S3 bucket that publishes 10 events per second with the function taking an average of three seconds to run, which equates to 30 concurrent executions (http://amzn.to/29nORER). If a Lambda function is throttled and continues to be invoked synchronously, Lambda will respond with a 429 error. It’s then up to the event source (for example, your application) to try invoking the function again. If a function was invoked asynchronously, AWS will automatically retry the throttled event for up to six hours with delays in between every invocation (http://amzn.to/29c7Bar).
Lambda functions execute in a container (sandbox), which provides isolation from other functions and an allocation of resources such as memory, disk space, and CPU. Container reuse is important to understand for more advanced uses of Lambda. When a function is instantiated for the first time, a new container is initialized and the code for the function is loaded (we say that the function is cold when this is done for the first time). If a function is rerun (within a certain period), Lambda may reuse the same container and skip the initialization process (we say that the function is now warm), thus making it available to execute code quicker.
Tim Wagner, the general manager of Lambda at AWS (http://amzn.to/237CWCk), makes an important point: “Remember, you can’t depend on a container being reused, since it’s Lambda’s prerogative to create a new one instead.” This means that every time you run a function, you should assume that you have a new container. But if you use the /tmp folder or touch the filesystem in other ways, your files or changes from the previous invocation may still be there. We’ve experienced this many times. If it happens to you, you’ll have to clean the /tmp directory manually.
Another important detail is what Wagner calls the freeze/thaw cycle. You can run a function and launch a background thread or a process. When the function finishes executing, the background process will become frozen. Lambda may reuse the container the next time you invoke the function and thaw the background process, thus resuming its execution. The background process will continue to run as though nothing happened. Keep this in mind if you decide to run background processes.
Here’s an experiment. Create any simple Hello World function in the AWS console and run it. You can easily do this by using the hello-world blueprint and then clicking the Test button in the console. Have a look at the duration in the summary in the bottom-left corner (figure 6.3).
Then run the test again and look at the duration in the summary (figure 6.4).
If you compare the duration of both executions, you’ll see that the time it takes to run a function for the first time is a lot longer than running it a second time. This is the result of the container reuse we described in the previous section. The first time the function is run (when it’s cold), the container needs to be created and the environment needs to be initialized. A lengthy initialization time may be especially noticeable in complex functions that have multiple dependencies. Reusing a container and running a function again is almost always much quicker.
You should try to reduce cold starts (when a function hasn’t been run for a long time and needs to fully initialize) to make the application appear more responsive. If you experience many cold starts, you can try a few steps to increase performance:
We touched on Lambda’s programming model back in chapter 3. Let’s look at it now in more detail from the perspective of the Node.js 4.3 runtime you’ve been using. These are the important elements to consider:
You’ve seen that the function handler is what the Lambda runtime calls to run your function. It’s the entry point. Lambda passes in the event data to the handler function as the first parameter, a context object as the second parameter, and a callback object as the third. The syntax for the function handler is as follows:
exports.handler = function(event, context, callback) { //code }
The callback object is optional and is used if you want to return information to the caller of the function or log an error. Over the next three sections we’ll describe event, context, and callback parameters in more detail.
You already saw the event object in action when you invoked Lambda functions in previous chapters. The event object contains information about the event and the source that triggered the Lambda function. It’s just a JSON object with an arbitrary number of properties that are specified by the event source.
You can look at sample event objects in Lambda’s console by following this process:
If you invoke a Lambda function via the AWS console, via the CLI, or through an API Gateway, you can create your own event object and customize the way it is structured.
The context object provides a number of useful properties for getting information about Lambda’s runtime. You can call a number of methods on the context object, such as done(), succeed(), and fail(). These methods were important in the Node.js 0.1 version of the Lambda runtime but aren’t needed in the Node.js 4.3 version. You can review appendix D if you want to know what these are. The other method on the context object that you might find useful is getRemainingTimeInMillis(). Calling this method returns the approximate remaining execution time. This function is valuable if you need to check how much time is left before a timeout (a Lambda function can run for a maximum of five minutes).
The context object also has these useful properties:
See http://amzn.to/1UK9eib for more information about the methods and properties available via the context object.
The callback function is an optional third parameter in the handler function. It’s used to return information to the caller in the RequestResponse invocation type, such as when a function is invoked via the API Gateway. The syntax for using the callback object is as follows:
callback(Error error, Object result)
The Error parameter is optional and is used when you want to specify information about a failed execution. The second parameter, also optional, is used to provide information to the caller when the function succeeds. Note that you need to pass null as the first parameter if you’re going to specify the second parameter and there’s no error. The following are examples of valid uses of callback:
You don’t need to specify any parameters in the callback if you don’t want to return information to the caller. You don’t even need to add callback() to your code if you don’t want to return a response or log an error. Lambda will call it for you implicitly if you don’t include it in your code. For more information on using the callback function, see the section titled “Using the Callback Parameter” at http://amzn.to/1NeqXM5.
Logging to CloudWatch can be done using console.log("message"). The other supported ways of logging are console.error(), console.warn(), and console.info(), but there’s no real distinction between them in terms of CloudWatch. If you invoke a Lambda function programmatically (see section 6.4 for more on this), you can add a LogType parameter to receive the last 4 KB of log data (it’s returned in the x-amz-log-results header of the response). The callback function will also log to a CloudWatch log stream if you provide a non-null value as the first parameter. At the end of the day, we highly recommend that you adopt a proper logging framework that will manage alert levels and log objects (for example, have a look at log at http://bit.ly/1VHIxuA).
When Lambda was originally released, it didn’t have support for versioning, aliases, or environment variables. But it’s now hard to imagine building and running a real production system without these features.
Versioning allows developers to create new versions of functions without overwriting previous ones. Once a new version of a function is published, the old version can still be accessed but it can’t be changed. Importantly, each version of a function has its own unique ARN, and each version can be invoked. To create a new version of a function, follow these steps:
If you click the Qualifiers drop-down and then select the Versions tab, you’ll see all current versions of the function (figure 6.6). The most recent version is always identified as $LATEST. If you don’t specify a version number when invoking a function, this is the function that’s invoked.
Your next question might be how to invoke a specific version of a function. That depends on where you’re trying to invoke the function from. If it’s the API Gateway, you can specify the function name and version with a colon in between, as you can see in figure 6.7 (for example, my-special-function:3).
If it’s S3, you can specify the function ARN, which, as we mentioned before, is unique for every version of the function (figure 6.8).
An alias is a pointer or a shortcut to a specific version of a Lambda function. It has an ARN just like a function, and it can be mapped to point to any function (or version) but not to another alias. Having an alias makes things easier when you need to switch from one version of a function to another. Imagine the following scenario:
With an alias, this scenario becomes into easier to manage:
Whenever you need to update the system to use a new version of a function, change the alias to point to that new version instead (figure 6.9). Event sources remain ignorant of the fact that an alias now points to a new version of a function and continue to operate as normal.
To create an alias for a function, follow these steps:
To view aliases for a function, use the Qualifiers drop-down, just as you did with versions (figure 6.10). A tab in the drop-down allows you to switch the view between versions and aliases. To delete an alias, choose Actions and select Delete Alias. Doing this deletes the alias and any related event source mappings that point to it. Everything else, including function versions, is left intact.
You already saw environment variables in chapter 5 when you created the user--profile Lambda function. Environment variables are key-value pairs, which can be set using the Lambda console, CLI, or the SDK. They can be referenced by the function’s source code and accessed during function execution.
By using environment variables for settings and secrets, you’ll avoid having to bake this information into the function’s code. And you’ll be able to change variables without having to modify and redeploy the function. Environment variables work with function versioning, which we’ve discussed in this section. A development version of a function can use a variable that points to the connection string of a development database. The same environment variable can point to the production version of a database for the production version of the function.
Figure 6.11 shows a part of the Lambda console (the Code tab) where you can set environment variables. You may notice that in this book we uppercase the names (keys) of environment variables (for example, UPLOAD_BUCKET). We chose to follow this convention. You don’t have to uppercase environment variable names if you don’t like that.
You can set environment variables using the AWS CLI. The CreateFunction and UpdateFunctionConfiguration APIs allow you to do that (more on these APIs in the next section).
Some environment variable key names are reserved. You can’t, for example, set a key called AWS_REGION or AWS_ACCESS_KEY. To see a full list of reserved variables, have a look at this page: http://amzn.to/2jDCgBa.
Environment variables can be accessed through process.env (for Node.js functions). If you wanted to print the value of the UPLOAD_BUCKET variable shown in figure 6.11, you’d add the following line to your function:
console.log(process.env.UPLOAD_BUCKET);
For sensitive data, you can choose to encrypt environment variables. You can do it in the console by enabling the Enable Encryption Helpers check box (figure 6.12). The first time you enable it, you’ll get a chance to create an encryption key using the AWS Key Management Service (KMS). You’ll then have this key available for encryption across all Lambda functions (in each region). You can, of course, create multiple keys too.
Having created a key, you’ll be able to encrypt all or some of the variables. In the console, you’ll see a button labeled Encrypt next to each environment variable. Use this button to encrypt the variable. The value will be immediately replaced with an encrypted string. You’ll also see a button called Code. You can click this button to get a snippet of code that shows how to decrypt the variable within the function.
Our advice is to use environment variables for settings and secrets whenever you can. Don’t bake these into your function. Use what the platform offers you and you’ll find life to be a lot easier.
So far, you’ve primarily used the AWS console to create and configure Lambda functions. It’s likely, though, that you’ll have to use the CLI at some point to create, update, configure, and delete functions, especially if you start thinking about automation.
If you followed chapter 3, you installed the AWS CLI (http://amzn.to/1XCoTOC). The CLI allows you to issue commands in the following form:
aws lambda <function-name> <command-options>
The page at https://docs.aws.amazon.com/cli/latest/reference/lambda/index.html describes available CLI commands. Let’s take delete alias (delete-alias) as an example. It has a few optional parameters, but at its core it’s as simple as running the following (where the --name flag is the name of the alias):
aws lambda delete-alias --function-name return-response --name production
Remember that if you invoke CLI commands, you must also have the right IAM security configured. If you were to try running the delete alias command right now, you’d receive an error message, such as “Client error (AccessDeniedException) occurred when calling the DeleteAlias operation.” To make it work you’d need to add the Delete-Alias permission to the user’s list of permissions.
In chapters 3 and 5 you deployed functions to AWS using the UpdateFunctionCode API. You did it by adding the following script to package.json:
aws lambda update-function-code --function-name arn:aws:lambda: us-east-1:038221756127:function:transcode-video --zip-file fileb://Lambda-Deployment.zip
But you had to create the function initially in the AWS console before you could use update-function-code. That’s a manual step and doesn’t fit with your ethos of complete automation. How would you go about creating and deploying a function entirely from the command line? Let’s step through an exercise to see how it’s done.
First, you need to update the lambda-upload user to IAM user to allow you to create functions. Back in chapter 4, you created a group called Lambda-DevOps and assigned the user lambda-upload to it. Now you need to edit the group’s policy and add a new permission:
You should also double-check that the user lambda-upload is in the Lambda-Upload-Policy group:
To create a function using the CLI, you need to provide a zip file with the source of the function or point to an S3 bucket that has the source. It’s easy to create a function locally and zip it up:
In the same directory as the zip file of the function, run the command given in the next listing (remember to update the role ARN; it should be the ARN of your own lambda-s3-execution-role). Take a look in the Lambda’s console to make sure it’s there.
aws lambda create-function --function-name cli-function -- handler index.handler --memory-size 128 --runtime nodejs4.3 --role arn:aws:iam::038221756127:role/lambda-s3-execution-role --timeout 3 -- zip-file fileb://index.zip --publish
This next listing shows a subset of the syntax you used with the create-function command, together with an explanation of each of the options. (Lambda supports many more settings and flags than shown in listing 6.3; refer to http://amzn.to/2jeCOfR if you want to see all of the options.)
Naturally, there are many other useful functions to invoke, including these:
If you’re using JavaScript (Node.js) to write your Lambda functions, you’ll have to deal with asynchronous callbacks. You’ve already seen these in action in chapter 3 and especially in the third Lambda function that you created in that chapter. Having multiple callbacks is frustrating and complex because following the logic of the program becomes difficult. If your function naturally leads to a series of sequential steps, you can adopt an async waterfall pattern and reduce the complexity of managing multiple asynchronous callbacks.
Async waterfall is a good pattern, but it’s by no means the only way you can deal with callback hell. ES6 supports promises, generators, and yields (http://bit.ly/2k70Zge), which you can use with Node.js 4.3 and Lambda. You could even try using ES7 features—like async/await and transpiling your code down to promise chains—but that could make debugging harder. In other words, read the next section and think about whether the async waterfall pattern is right for you. In many cases, especially if you’re dealing with legacy code that hasn’t been ported to Node.js 4+, knowing and applying a pattern like this is a good idea.
Async (http://bit.ly/23RfWVe) is a JavaScript library that can be installed as an npm module. It has several powerful features, one of them being support for the waterfall pattern. This pattern allows you to run a set of functions one after another, passing the result of one function into the next one using a callback function. If one of the functions passes an error into the callback, the execution of the waterfall is stopped, and the next task is not invoked (figure 6.14).
The following listing shows a general example of an async waterfall pattern (this listing is adopted from an example given in http://bit.ly/1WaSNui).
In listing 6.4, take note of the callback function, which is used often. This function must be called on the completion of each task. The first parameter in the callback represents an error. If there’s no error, use a null. The other parameters can be whatever you want. They’re passed on to the next task.
This callback function is similar to the callback you’ve already seen in Lambda. You must not confuse the two callback functions, however, so we recommend naming the callback used in async waterfall to something else (such as next).
As a clone of YouTube, 24-Hour Video needs to list videos that users can click and view. You don’t have a database at the moment to store URLs to your videos, but you can create a Lambda function to make a list of files in the S3 bucket. This function can be invoked via the API Gateway, and it can return a list of URLs to your videos. You can use async waterfall for this example because you need to take a few steps in series.
Create a new function on your system and name it get-video-list. Here’s how to do this:
Add the async module using npm. In the terminal, change to the directory of the function and run the following:
npm install async --save
You should also run npm install to make sure that the AWS SDK is installed. If you look at package.json, there should be two dependencies: async and aws-sdk.
Now (if you followed section 6.4.2) you can create the required Lambda function in AWS using the command npm run create. If you skipped over section 6.4.2, you’ll have to create the get-video-list function in the AWS console yourself.
This function has a fairly simple implementation, as shown in listing 6.6. Notably, it doesn’t take into account some scenarios, such as what happens when there are many files in the S3 bucket (the S3 listObjects operation returns up to 1000 objects in the bucket). The function is also not very efficient. But it’s a good temporary measure until we introduce a proper database, and it’s a good way to show how the waterfall pattern is used.
Deploy the function by executing npm run deploy from the directory of the function.
The code in listing 6.6 uses two environment variables: BUCKET and BASE_URL. The BUCKET variable is the name of the second S3 bucket with transcoded files. BASE_URL is a base address for S3 buckets, which is https://s3.amazonaws.com. You must add these two variables for the function to work. In the Lambda console, click the get-video-list function, and add these two environment variables at the bottom of the Code tab (figure 6.15).
The simplest way to test this function is to jump into the AWS console, click Lambda, and then click get-video-list. From there click the Test button. If you get the Input Test Event dialog, click Save And Test to proceed. You should see a list of URLs (if you have mp4s in the bucket) under the Execution Result heading toward the bottom of the page (figure 6.16).
The AWS CLI can invoke Lambda functions from the command line. It supports both invocation types, RequestResponse and Event. The syntax for the command can be found in http://amzn.to/269Z2U2. If you decide to try a synchronous Request-Response invocation, you need to provide at least two parameters: the function name and the output file that will contain the response from the function.
To invoke the get-video-list function, you need to run the following from your terminal:
aws lambda invoke --function-name get-video-list output.txt
Remember to grant the right permission (lambda:InvokeFunction) to your IAM user if you decide to use this.
In addition to waterfall, the async library supports series and parallel patterns of execution. The series pattern is similar to waterfall; it invokes a series of functions one by one. Values (results) are passed into the optional callback function at the very end once the series has finished (figure 6.17).
The parallel pattern is used to run functions in parallel without waiting for other functions to finish. Once all functions have completed, the results are passed into the optional (final) callback (figure 6.18).
This advice is a given for most developers. Identify code that’s repeated in multiple Lambda functions and move it to another file so that this code is written only once (the Don’t Repeat Yourself principle). You can import your libraries using node’s require().
Let’s see how to practice what we preach and build a library for sending emails using Amazon’s Simple Email Service (SES). You can use it to send email when a user uploads a new video or as a way to enable messaging between users. There are two ways you can include this library with the rest of your code:
We’ll go with the second method in this example, but as part of an exercise later on, we’ll ask you to create an npm module for your library, deploy it to the npm repository, and then install it using npm install.
Create a directory called lib for your library. In this directory make a file called email.js and copy the following listing into it.
The code in listing 6.7 has a function called send, which can be invoked by external code. It takes four parameters: an array of receiver emails, the sender’s own email, a subject, and a message. To use this library in your Lambda functions, follow these steps:
var email = require('email');
email.send(['[email protected]'], '[email protected]', 'Subject', 'Body');
You will have noticed that in this library you imported async but didn’t bother to run npm install. This is because the library you created will be shipped with a Lambda function that will hopefully have the right npm modules, including async, installed. To be on the safe side, however, you could write a package.json for this library and npm install needed dependencies. In fact, you should do this if you decide to build libraries properly.
Here are a few notes about sending email using SES:
Building on advice in the previous section, we recommend moving all of your domain/business logic to a different file/library. Your Lambda handler should be a thin wrapper that executes code stored in another file. Having the bulk of your logic in a separate file will lead to an implementation that’s more testable and is much more decoupled from Lambda. If one day you decide to move away from Lambda, you’ll find it easier to port your code to a new serverless compute service.
There are two main ways you can test a Lambda function. You can run tests locally (or during continuous integration/deployment) and you can test the function once it’s deployed to AWS.
Back in chapter 3, you installed an npm module called run-local-lambda. That package allowed you to invoke a Lambda function locally on the computer and pass in an event, a context, and a callback function. Going forward, however, you need to set up a much more rigorous and robust system for executing tests. You need to have a way to mock dependencies, spy on variables and functions, and manage setup and teardown procedures. This section looks at how to put together a good approach to testing.
Let’s look at how to test Lambda functions on your computer (later, you’ll make these tests run as part of your continuous integration/deployment pipeline). To make this more interesting, you’ll write tests for the get-video-list function you created in section 6.5.3. You’ll use Mocha, Chai, Sinon, and rewire to help you write and run your tests.
In your terminal, change to the directory of the function you created in section 6.5.3 and run the following npm install commands to download the required components:
We should note that Lambda functions are no different from any other regular Node.js application. You can use a different JavaScript framework or assertion library if you prefer.
Having installed the modules, create a new subdirectory called test. In this subdirectory create a file called test.js and open it in your favorite text editor. Copy the next listing into this file.
Having implemented listing 6.8, run mocha from the directory of the function. You should see output similar to figure 6.20.
Let’s do a quick review of what happens in your test file:
Testing is a broad and complex subject that will take time to master and get right. Thankfully, testing Lambda functions is straightforward compared to more complex Node.js applications. If you want another example, similar to the one you just completed, have a look at http://bit.ly/1MQc4zO.
Our recommendation is to write tests for each Lambda function you create. Once you have a template for wiring up and mocking dependencies (and you can begin by taking listing 6.8 and repurposing it for your needs), creating new tests should become relatively easy.
You’ve written a number of wonderful tests on your system and deployed a function to AWS. It’s a good idea to test your function in AWS to make sure that it works as you expect. An obvious way to do it is to click the Test button in the console and provide an event for your function to consume. Luckily, there’s an even better way to do testing using the unit and load test harness blueprint provided by AWS. This blueprint creates a Lambda function for you that can invoke a Lambda function you wish to test and record the results in a DynamoDB table.
Tim Wagner originally wrote about this in a blog post (http://amzn.to/1Nq37Nx) titled “A Simple Serverless Test Harness using AWS Lambda.” You can configure this test harness as follows:
To correctly run the lambda-test-harness function, you need to create an event object that describes a test configuration and pass it to the test harness function. The next listing shows an example test configuration for the get-video-list function you developed earlier in this chapter. Note that the event is empty because get-video-list doesn’t use it during execution.
To run the test harness function, click the Test button in the AWS console (assuming you have the function open) and type the configuration from listing 6.9 into the input test event dialog. Then click Save and Test.
Look at the unit-test-results table in DynamoDB for information after executing the function to see the results. To perform a load test, modify the configuration slightly by changing the operation from unit to load and setting a desired number of iterations. The next listing shows a configuration you can use to execute the function 50 times.
Having a mix of tests to run in your local environment and in AWS will give you confidence to make changes and improvements. Don’t neglect testing, and do it from the very start.
You learned a lot about Lambda in this chapter, but there’s no better way to test your knowledge than trying a few exercises. See if you can do the following:
A compute service such as Lambda is the heart of serverless architecture. It’s the glue that holds everything together. It can serve as a back end for your application or act as a coordinator between other services in your system. In this chapter, we looked at the following:
In the next chapter, we’ll look at the API Gateway and discuss how to create robust back ends for web and mobile applications.
3.23.20.236