Enabling Compression for Lambda with AWS HTTP APIs

Enabling Compression for Lambda with AWS HTTP APIs

AWS HTTP APIs provides a new way to deploy REST-based APIs in AWS; providing a number of simplifications over the original REST APIs.

However, when working with HTTP APIs we need to be aware of a few gotchas, such as what types to use for handler arguments. REST APIs also used to provide a way to enable payload compression. For HTTP APIs though, we need to compress the payloads ourselves.

Thankfully, this is relatively straightforward and I will explain each step required in the below. For those looking for a quick solution, I’ve created a library lambda-compression, you can use as follows.

Compress with Library

The lambda-compression library provides only one method compress that accepts the event variable that is passed into handler functions by the HTTP API and a ‘structured’ result (see Lambda function response for format 2.0).

The compress function will return a structured result that can returned as the result of the handler function.

The library can be installed as a Node dependency:

npm i lambda-compression

yarn add lambda-compression

Here an example implementation using JavaScript:

import { compress } from 'lambda-compression';

export const handler = async (event, context) => {
  return compress(event, {
    statusCode: 201,
    headers: {
      'Content-Type': 'application/json',
    },
    body: '{"data":"hello"}',
  });
};

And here an example implementation using TypeScript:

import { compress } from 'lambda-compression';

import {
  Handler,
  APIGatewayProxyEventV2,
  APIGatewayProxyResultV2,
} from 'aws-lambda';

type ProxyHandler = Handler<APIGatewayProxyEventV2, APIGatewayProxyResultV2>;

export const handler: ProxyHandler = async (event, context) => {
  return compress(event, {
    statusCode: 201,
    headers: {
      'Content-Type': 'application/json',
    },
    body: '{"data":"hello"}',
  });
};

Steps required for Compression

The logic required for implementing compression is quite simple since we can rely on the zlib package provided in Node.js.

See a full source code example here: lambdaCompression.ts

Essentially we need to:

  • Determine which compression formats the client accepts by querying the accept-encoding header.
  • If the client does not support compression, return the uncompressed payload.
  • If the client does support compression:
    • apply the supported compression format (br, gzip or deflate),
    • Base64 encode the result,
    • set the isBase64Encoded property in the result, and
    • set the Base64 encoded result as the body of the returned response.

Final Thoughts

Compression can be CPU intensive, thus it could be prudent to cache the compressed results if the same result can be expected to be returned repeatedly. It is also possible to place your API behind a CloudFront Distribution that can take care of compressing payloads under limited circumstances. Lastly, reverting back to using a REST API also enables to use a built-in compression function.

If you have any ideas of improving the library, please be welcome to submit an issue 🤗.


Cover image by iam_os.