Lambda functions can return multiple values for the same HTTP header.

Let’s say you’re building an API gateway endpoint that needs to set a Set-Cookie header. The standard way to do this is with a headers object in your Lambda response:

{
  "statusCode": 200,
  "headers": {
    "Content-Type": "application/json",
    "Set-Cookie": "sessionid=abcdef12345; HttpOnly; Secure"
  },
  "body": "{\"message\": \"Hello, world!\"}"
}

But what if you need to return multiple Set-Cookie headers? For example, when authenticating a user and setting both a session cookie and a refresh token cookie. If you try to put them in the same string, separated by a comma, it won’t work as expected because the Set-Cookie header is designed to be sent multiple times, not as a comma-separated list.

Here’s how you’d actually do it in your Lambda function, returning multiple Set-Cookie headers using an array:

import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'application/json',
            'Set-Cookie': [
                'sessionid=abcdef12345; HttpOnly; Secure',
                'refreshtoken=xyz7890; HttpOnly; Secure'
            ]
        },
        'body': json.dumps({'message': 'Cookies set successfully!'})
    }

When API Gateway receives this response, it knows how to translate the array of strings for Set-Cookie into individual Set-Cookie headers in the HTTP response sent to the client. The client’s browser will then see two distinct Set-Cookie headers.

This array-based approach isn’t limited to Set-Cookie. Any HTTP header that can technically appear multiple times in an HTTP request or response can be represented this way. Common use cases include Access-Control-Allow-Origin (for CORS preflight responses with multiple origins), or custom headers you might be using for specific application logic.

The key is that API Gateway, when configured to proxy the response, inspects the headers object. If it finds a value that is an array of strings, it will serialize each element of the array as a separate instance of that header in the final HTTP response. If the value is a single string, it’s treated as a single header value.

This mechanism allows you to construct more complex and compliant HTTP responses directly from your Lambda function without needing to manually format or concatenate header values, which could lead to syntax errors or incorrect parsing by clients.

The most surprising thing about this is that it’s a built-in feature of how API Gateway interprets Lambda proxy integration responses, and it’s not something you typically need to explicitly configure in API Gateway itself. The magic happens in how the headers object is structured in your Lambda’s return payload.

If you’re using a framework or library to abstract Lambda, ensure it correctly handles the serialization of array-valued headers. Some older or simpler abstractions might only expect string values and could flatten arrays into a single string, often with unintended consequences.

The next concept you’ll likely encounter is handling different response types for different HTTP methods or status codes within the same Lambda function.

Want structured learning?

Take the full Lambda course →