Deep Dive: Lambda’s Request Payload Size Limit (2/2)

Photo by patricia serna on Unsplash

What is the limit?

The Lambda quotas page lists both the request and response payload limits as same 6 MB for synchronous invocations.

What is a request payload?

It’s important to really understand how our Lambda function receives its payload.

The JSON that you want to provide…

The HTTP request body must be able to be deserialized as JSON (i.e. using JSON.parse). This means, for example, strings must be wrapped in double-quotes.

…to your Lambda function as input

The parsed payload becomes the event passed to your handler, for example:

  • Python: def handler_name(event, context):
  • JavaScript: exports.handler = async function(event, context) {

How I’m testing

I’ve created a function named test-function. It stringifies event back to JSON and returns an accurate count of characters and bytes.

Proving a point

If you add the --debug argument, the AWS CLI logs details of the HTTP request and response. This provides an quick way to check that it really is sending the payload in the body. The Content-Length header is in there too.

Making request for OperationModel(name=Invoke) with params:
{
"body": b'"AAAAAA"',
"method":"POST",
"url": "https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/test-function/invocations",
...
}

Breaking the limit

When I send 7 million A letters, I get the following error back from Lambda:

An error occurred (RequestEntityTooLargeException) when calling the Invoke operation: Request must be smaller than 6291456 bytes for the InvokeFunction operation

Lambda’s payload size limit is 100 bytes more for responses than requests, but the docs say they’re the same.

Maybe the response limit is bigger in case you want to return the request alongside something else? For example:

{
"jobCreated": true,
"jobId": 1234,
"request": "AAAAAAAAAAAA...AAAAAAAAA"
}

Making Lambda happy

Based on what we learned in the previous post, we should already know how to make Lambda happy. We send the letter A 6,291,454 times along with two double-quotes to reach the 6,291,456 limit. Right?

API Gateway: proxy integrations

I’ve modified the example function to return an object with statusCode and body properties like API Gateway expects for proxy integration responses:

  • ,“content-type”:”application/x-www-form-urlencoded”
  • ,”content-type”:[“application/x-www-form-urlencoded”]
  • ”\”AA\””

“The JSON that you want to provide to your Lambda function as input”

Lambda says it wants a JSON payload so we had to add double-quotes when invoking the function directly. But why don’t we need them when invoking via API Gateway?

Lost control

The baseline size of the API Gateway proxy integration object is variable.

API Gateway: AWS Service integration

Before the “Lambda Function” integration (proxy integration) existed, the only way to make API Gateway invoke a Lambda function was using an AWS Service integration.

Bonus: emulating the proxy inegration using VTL

We can execise our control using VTL mapping templates. The VTL below instructs API Gateway to send Lambda an object containing body (JSON stringified request body) and headers (containing only the content-type header). Everything else is discarded.

Skipped: binary payloads

API Gateway also supports an isBase64Encoded property which can also be emulated with VTL, but I’m ignoring that here for simplicity.

Summary

  • When the Lambda docs say 6 MB, they mean 6,291,456 bytes for requests and 6,291,556 bytes for responses.
  • Lambda functions can return 100 bytes more than they can receive.
  • Lambda request payloads must always be valid JSON.
  • API Gateway proxy integrations map your request body into the body property of a JSON object, so it’s always valid JSON.
  • The size of this object is variable based on headers, API Gateway configuration, and more.
  • You can use the older AWS Service integration to gain full control of request and response payloads.
  • Add the --debug argument to any AWS CLI call to see details of SigV4 signing and the HTTP request/response.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store