Put Your Alexa Skill Code On A Diet with AWS Lambda Layers

Ceyhun Özgün
4 min readFeb 6, 2019

--

When I was in a rush to complete my Alexa Skill for Amazon Alexa Skills Challenge: Multimodal Hackathon, I was testing my skill again and again after making some changes.

When I started developing my Alexa skill, I was pretty sure that I should write unit tests for my code to be confident when making changes. After a short Google search for Node.js testing tools, I have decided to use Mocha for testing my sub-modules that are not specific to Alexa Skills Kit SDK. One example sub-module was user profile sub-module that saves the profiles to Amazon DynamoDB. Also using Chai for assertions, I definitely saw the value of writing the unit tests while developing the skill.

But when it comes to testing whole skill flow a few times, it was really boring. I noticed that there were emerging tools for testing your AWS Lambda functions and Alexa Skills locally, but I didn’t have time to learn a new tool while I am trying to not miss the deadline.

After completing my submission on time, I had time to think about improving the process. And I decided to write about it in case it helps to an another Alexa developer.

In this post, I will show a solution for reducing the code transferred to Amazon S3. If I have time, I will write about the tools that allows testing Alexa Skills locally.

AWS Lambda Layers

The Problem

The biggest problem I have experienced was uploading 9.4MB (zipped) Node.js Lambda function code to my AWS S3 bucket every time I have changed the Lambda Function code.

Even if I have changed a single line whole code with all the Node modules (approximately 50 MB unzipped) had to be transferred to S3 and it teachs you being patient while you are waiting the transfer to finish :).

The biggest contributors to this size are Alexa Skill Kit (ASK) SDK v2 for Node.js, AWS SDK for Node.js and Moment.js. And if you develop many skills you transfer all these modules with each of your Alexa skills.

The Solution

Trying AWS Lambda Layers was on my mind since it was announced at re:Invent 2018.

Lambda Layers allows you to reuse common code across many Lambda functions. A layer is basically a zip archive that contains libraries that are used by many Lambda functions.

In case of Node.js, a Lambda layer can contain Node.js npm modules.

By putting common Node.js modules in a Lambda Layer and referencing this layer in your Lambda functions you can reduce the size of Lambda code.

In my case I have put common Node.js modules that I have used for developing Alexa skills in to my AlexaSkillNodejsLambdaLayer. These modules are below:

By using this method I have managed to reduce the Lambda code archive size to approximately 3.3MB from 9.4MB.

Preparing The Layer Code

First we should create an empty directory.

mkdir AlexaSkillNodejsLambdaLayer

If you use Node.js 8 runtime create another directory named node8. If you use a Node.js runtime version lower than 8, this directory is not needed.

Cd into the directory and install needed node modules.

npm install aws-sdk ask-sdk moment config ssml-builder amazon-date-parser

After the installation, the directory structure below the root directory should look like below.

C:\temp\AlexaSkillNodejsLambdaLayer>tree
.
└───nodejs
└───node8
└───node_modules
├───amazon-date-parser
├───ask-sdk
├───ask-sdk-core
├───ask-sdk-dynamodb-persistence-adapter
├───ask-sdk-model
├───ask-sdk-runtime
├───aws-sdk
├───base64-js
├───buffer
├───config
├───events
├───ieee754
├───isarray
├───jmespath
├───json5
├───minimist
├───moment
├───punycode
├───querystring
├───sax
├───ssml-builder
├───url
├───uuid
├───xml2js
└───xmlbuilder

Create the archive of the code by executing the command below at the root directory.

jar -cvf AlexaSkillNodejsLambdaLayer.zip .

Now the layer code is ready.

Creating The Layer

You can create the layer by executing the command below.

aws s3 cp AlexaSkillNodejsLambdaLayer.zip s3://alexaskilllayeraws lambda publish-layer-version --layer-name AlexaSkillNodejsLambdaLayer --content S3Bucket=alexaskilllayer,S3Key=AlexaSkillNodejsLambdaLayer.zip --compatible-runtimes nodejs8.10

Every time you execute the command above you publish a new layer version. You can reference the versioned layer in your Lambda functions.

Referencing The Layer in Lambda Functions

After you have created the layer you can update your Lambda function to use the created layer. You can use both Amazon Lambda Console and AWS CLI to update the function. You can use the command line below to reference the layer. You should replace region and account_id in the layer ARN.

aws lambda update-function-configuration --function-name MyAlexaSkillLambda --layers arn:aws:lambda:region:account_id:layer:AlexaSkillNodejsLambdaLayer:1

Also, you should update your Lambda code archive generation command to not include the modules in your archive. You can’t simply delete the sub-directories below node_modules directory because they are used when you test it locally. You can use zip command with -x flag to exclude the specific node modules like below. In the command below I have excluded Mocha and Chai testing modules also.

jar -cvf MyAlexaSkillLambda.zip *.js
jar -uvf MyAlexaSkillLambda.zip *.json
jar -uvf MyAlexaSkillLambda.zip config/*
jar -uvf MyAlexaSkillLambda.zip intents/*
zip -9 -r MyAlexaSkillLambda.zip node_modules -x node_modules/mocha/\* node_modules/chai/\* node_modules/ask-sdk-core/\* node_modules/ask-sdk-model/\* node_modules/ask-sdk-runtime/\* node_modules/aws-sdk/\* node_modules/amazon-date-parser/\* node_modules/ssml-builder/\* node_modules/moment/\*

Conclusion

In this post, I have shown that the recently announced AWS Lambda Layers can be used to make Lambda functions for Alexa Skills slimmer. Lambda Layers also allows you to update common components easily.

If you liked this post, please clap or share.

Thanks for reading.

--

--