Dustin Coates in Alexa

How an AWS Lambda Function Works on a High Level

While I don’t have any firm numbers, I would expect that most Alexa Skills are running on AWS Lambda. The tooling is all there for you to get started, so you’d have to have a pretty good reason to not use Lambda. Of those, I’d wager that most are in JavaScript. Nothing more than a hunch on that one, to be honest.

(Time out: this post is high-level, but if you want to know about Lambda from top-to-bottom, check out AWS Lambda in Action or Serverless Architecture on AWS. (P.S. If you buy either of those books from those links, I get a tiny, tiny amount of money, but my recommendations are completely independent of that.))

When I first started using Lambda, it seemed like a real black box. What’s going on in here?! Truth talk, though: it’s no more a black box than any other endpoint where your code receives data. Like say you’ve got an old-school, traditional web API and a client can post data. That’s not all that different from what’s going on with Lambda.

Whenver a Lambda function (you can think of it as an endpoint of sorts, but from this point on I’m going to keep calling it a function) is invoked, it’s provided three arguments: event, context, and callback.

event

This is the main data that is provided to our function. This event can be simple:

{
  "key3": "value3",
  "key2": "value2",
  "key1": "value1"
}

to complex:

{
  "session": {
    "new": false,
    "sessionId": "amzn1.echo-api.session.[unique-value-here]",
    "attributes": {},
    "user": {
      "userId": "amzn1.ask.account.[unique-value-here]"
    },
    "application": {
      "applicationId": "amzn1.ask.skill.[unique-value-here]"
    }
  },
  "version": "1.0",
  "request": {
    "locale": "en-US",
    "timestamp": "2016-10-27T21:06:28Z",
    "type": "IntentRequest",
    "requestId": "amzn1.echo-api.request.[unique-value-here]",
    "intent": {
      "slots": {
        "Item": {
          "name": "Item",
          "value": "snowball"
        }
      },
      "name": "RecipeIntent"
    }
  },
  "context": {
    "AudioPlayer": {
      "playerActivity": "IDLE"
    },
    "System": {
      "device": {
        "supportedInterfaces": {
          "AudioPlayer": {}
        }
      },
      "application": {
        "applicationId": "amzn1.ask.skill.[unique-value-here]"
      },
      "user": {
        "userId": "amzn1.ask.account.[unique-value-here]"
      }
    }
  }
}

This second event is a sample event for an Alexa intent (RecipeIntent) invocation. A Lambda function can be invoked in many different ways (for example, using Amazon API Gateway), but on this blog we’re mainly concerned with Alexa, Lex, and chat bots.

The big takeway: event is just an object of data.

context

The context object is also just a JavaScript object, but it serves a different purpose. The context obect provides information on the current execution context.

It has a single function: getRemainingTimeInMillis, because why, oh why, Amazon could you not use MS for milliseconds? Sorry—a bit of a diversion. This function tells you how long until the current function will timeout.

It also has 10 different properties:

  • callbackWaitsForEmptyEventLoop: whether the callback will wait until the Node.js event loop is empty before returning the output to the function caller. You can update this.
  • functionName: what function is currently running?
  • functionVersion: which version?
  • invokedFunctionArn: which ARN was used to invoke the function?
  • memoryLimitInMB: this value is configured at setup of the Lambda function and can be changed, but not within the code.
  • awsRequestID: this ID is sent back to the client and stays the same even if the function is retried.
  • logGroupName: which log group in CloudWatch your logs can be found for this function.
  • logStreamName: more information on where in CloudWatch to go for the logs.
  • identity: relevant only if invoked via the AWS Mobile SDK.
  • clientContext: again only relevent for the AWS Mobile SDK, it gives information on the application and the device.
  • done, succeed, fail: only used in the Node.js v0.10.42 runtime, which is on its way to being completely deprecated. These methods are replaced by the callback.

To be completely honest, you aren’t going to use the context object all that much.

callbck

The callback is used if you want to send information back the caller’s way. It’s optional and works in the newer Node.js runtimes supported by Lambda (4.3 and 6.10 currently), with function termination being handled in the oldest version by methods on context, as noted above. The callback accepts two arguments: error (which is sent to CloudWatch as well as the caller) and result, which can be anything that can be sent to JSON.stringify.

There is obviously a lot to know about AWS Lambda, but understanding the function signature is perhaps the most important thing to understand for building for conversational platforms.