@interlace/serverless
API Gateway CachingRecipes

Cache Key Parameters

Define what makes a cache entry unique — path, query string, header, and body parameters.

Overview

Without cache key parameters, all requests to the same path return the same cached response. Cache key parameters tell API Gateway to create separate cache entries based on request values.

The same recipe in all four config formats Serverless Framework supports — pick whichever your project uses.

TypeScript users — typing the `caching:` field

The official @types/serverless (serverless/aws.d.ts) doesn't include a caching shape on http events — that's a plugin-level extension. Two options to keep serverless.ts clean:

  1. Recommended. Import the typed shapes our plugin exports and assert at the assignment site:

    import type { EndpointCachingConfig } from '@interlace/serverless-api-gateway-caching';
    
    const caching: EndpointCachingConfig = {
      enabled: true,
      cacheKeyParameters: [{ name: 'request.path.id' }],
    };
    
    // attach to the http event with `as unknown as Record<string, unknown>`
    // or extend the framework's `Http` type via module augmentation.
  2. Quick escape hatch. Inline cast: caching: ({ enabled: true, ... } as unknown as never). Keeps the rest of the config typed; loses safety on the caching subtree only.

The TypeScript snippets below assume option 1 — replace the inline objects with values typed against EndpointCachingConfig. We're tracking native @types/serverless integration in the plugin's roadmap.

Path, Query String, and Header

serverless.yml
functions:
  listCats:
    handler: src/handler.list
    events:
      - http:
          path: /cats
          method: get
          caching:
            enabled: true
            cacheKeyParameters:
              - name: request.path.id
              - name: request.querystring.page
              - name: request.querystring.limit
              - name: request.header.Accept-Language
serverless.ts
const serverlessConfiguration: AWS = {
  functions: {
    listCats: {
      handler: 'src/handler.list',
      events: [
        {
          http: {
            path: '/cats',
            method: 'get',
            caching: {
              enabled: true,
              cacheKeyParameters: [
                { name: 'request.path.id' },
                { name: 'request.querystring.page' },
                { name: 'request.querystring.limit' },
                { name: 'request.header.Accept-Language' },
              ],
            },
          },
        },
      ],
    },
  },
};
serverless.js
module.exports = {
  functions: {
    listCats: {
      handler: 'src/handler.list',
      events: [
        {
          http: {
            path: '/cats',
            method: 'get',
            caching: {
              enabled: true,
              cacheKeyParameters: [
                { name: 'request.path.id' },
                { name: 'request.querystring.page' },
                { name: 'request.querystring.limit' },
                { name: 'request.header.Accept-Language' },
              ],
            },
          },
        },
      ],
    },
  },
};
serverless.json
{
  "functions": {
    "listCats": {
      "handler": "src/handler.list",
      "events": [
        {
          "http": {
            "path": "/cats",
            "method": "get",
            "caching": {
              "enabled": true,
              "cacheKeyParameters": [
                { "name": "request.path.id" },
                { "name": "request.querystring.page" },
                { "name": "request.querystring.limit" },
                { "name": "request.header.Accept-Language" }
              ]
            }
          }
        }
      ]
    }
  }
}

How cache entries are created

Given the configuration:

serverless.yml
caching:
  enabled: true
  cacheKeyParameters:
    - name: request.path.pawId
    - name: request.querystring.catName
serverless.ts
caching: {
  enabled: true,
  cacheKeyParameters: [
    { name: 'request.path.pawId' },
    { name: 'request.querystring.catName' },
  ],
}
serverless.js
caching: {
  enabled: true,
  cacheKeyParameters: [
    { name: 'request.path.pawId' },
    { name: 'request.querystring.catName' },
  ],
}
serverless.json
{
  "caching": {
    "enabled": true,
    "cacheKeyParameters": [
      { "name": "request.path.pawId" },
      { "name": "request.querystring.catName" }
    ]
  }
}
  • GET /cats/4 → cache entry for pawId=4, catName=undefined
  • GET /cats/34?catName=Dixon → cache entry for pawId=34, catName=Dixon
  • GET /cats/72?catName=Tsunami&furColour=white → cache entry for pawId=72, catName=Tsunami (ignores furColour)

Cache key parameter names are case sensitive. request.header.accept-language and request.header.Accept-Language create different cache entries.

Body-Based Cache Keys

For POST endpoints (e.g., GraphQL), cache based on the request body.

Entire body

serverless.yml
caching:
  enabled: true
  cacheKeyParameters:
    - name: integration.request.header.bodyValue
      mappedFrom: method.request.body
serverless.ts
caching: {
  enabled: true,
  cacheKeyParameters: [
    {
      name: 'integration.request.header.bodyValue',
      mappedFrom: 'method.request.body',
    },
  ],
}
serverless.js
caching: {
  enabled: true,
  cacheKeyParameters: [
    {
      name: 'integration.request.header.bodyValue',
      mappedFrom: 'method.request.body',
    },
  ],
}
serverless.json
{
  "caching": {
    "enabled": true,
    "cacheKeyParameters": [
      {
        "name": "integration.request.header.bodyValue",
        "mappedFrom": "method.request.body"
      }
    ]
  }
}

JSONPath expression

Cache by a specific field in the body:

serverless.yml
caching:
  enabled: true
  cacheKeyParameters:
    - name: integration.request.header.cityCount
      mappedFrom: method.request.body.cities[0].petCount
serverless.ts
caching: {
  enabled: true,
  cacheKeyParameters: [
    {
      name: 'integration.request.header.cityCount',
      mappedFrom: 'method.request.body.cities[0].petCount',
    },
  ],
}
serverless.js
caching: {
  enabled: true,
  cacheKeyParameters: [
    {
      name: 'integration.request.header.cityCount',
      mappedFrom: 'method.request.body.cities[0].petCount',
    },
  ],
}
serverless.json
{
  "caching": {
    "enabled": true,
    "cacheKeyParameters": [
      {
        "name": "integration.request.header.cityCount",
        "mappedFrom": "method.request.body.cities[0].petCount"
      }
    ]
  }
}

Mixed sources

Combine query string and body parameters:

serverless.yml
caching:
  enabled: true
  cacheKeyParameters:
    - name: request.querystring.catName
    - name: integration.request.header.furColour
      mappedFrom: method.request.body.furColour
serverless.ts
caching: {
  enabled: true,
  cacheKeyParameters: [
    { name: 'request.querystring.catName' },
    {
      name: 'integration.request.header.furColour',
      mappedFrom: 'method.request.body.furColour',
    },
  ],
}
serverless.js
caching: {
  enabled: true,
  cacheKeyParameters: [
    { name: 'request.querystring.catName' },
    {
      name: 'integration.request.header.furColour',
      mappedFrom: 'method.request.body.furColour',
    },
  ],
}
serverless.json
{
  "caching": {
    "enabled": true,
    "cacheKeyParameters": [
      { "name": "request.querystring.catName" },
      {
        "name": "integration.request.header.furColour",
        "mappedFrom": "method.request.body.furColour"
      }
    ]
  }
}

Catch-All Path Parameters

For greedy path routes ({proxy+}):

serverless.yml
functions:
  proxy:
    handler: src/proxy.handle
    events:
      - http:
          path: /api/{proxy+}
          method: get
          caching:
            enabled: true
            cacheKeyParameters:
              - name: request.path.proxy
serverless.ts
functions: {
  proxy: {
    handler: 'src/proxy.handle',
    events: [
      {
        http: {
          path: '/api/{proxy+}',
          method: 'get',
          caching: {
            enabled: true,
            cacheKeyParameters: [{ name: 'request.path.proxy' }],
          },
        },
      },
    ],
  },
}
serverless.js
functions: {
  proxy: {
    handler: 'src/proxy.handle',
    events: [
      {
        http: {
          path: '/api/{proxy+}',
          method: 'get',
          caching: {
            enabled: true,
            cacheKeyParameters: [{ name: 'request.path.proxy' }],
          },
        },
      },
    ],
  },
}
serverless.json
{
  "functions": {
    "proxy": {
      "handler": "src/proxy.handle",
      "events": [
        {
          "http": {
            "path": "/api/{proxy+}",
            "method": "get",
            "caching": {
              "enabled": true,
              "cacheKeyParameters": [{ "name": "request.path.proxy" }]
            }
          }
        }
      ]
    }
  }
}

Cache entries:

  • GET /api/usersproxy=users
  • GET /api/users/123proxy=users/123

Limitations

  • Multi-value query strings (request.multivaluequerystring.*) and multi-value headers (request.multivalueheader.*) are not supported as cache key parameters. This is an AWS API Gateway limitation, not a plugin choice — AWS rejects these as Invalid mapping expression. The same limitation applies to the community serverless-api-gateway-caching plugin.
  • Body-based cache keys require an integration request mapping (handled automatically by the plugin).
  • httpApi (HTTP API) events are not supported — API Gateway HTTP APIs do not support caching (AWS docs).

On this page