Stage variables in API Gateway are a powerful, yet often misunderstood, mechanism for managing environment-specific configuration for your APIs.

Let’s see them in action. Imagine you have an API that needs to call out to a different backend service depending on whether it’s deployed to dev, staging, or prod.

{
  "id": "abc123xyz",
  "name": "MyAwesomeAPI",
  "restApiId": "abc123xyz",
  "stageName": "dev",
  "description": "",
  "cacheClusterEnabled": false,
  "cacheClusterSize": null,
  "variables": {
    "backendEndpoint": "https://dev.my-backend.com/v1",
    "apiKey": "dev-api-key-12345"
  },
  "deploymentId": "abcdef1234567890",
  "createdDate": "2023-10-27T10:00:00Z",
  "lastUpdatedDate": "2023-10-27T10:05:00Z"
}

In this example, the dev stage has two variables: backendEndpoint set to https://dev.my-backend.com/v1 and apiKey set to dev-api-key-12345.

Now, within your API Gateway method request configuration, you can reference these variables. For instance, if you have an integration request that calls an HTTP backend, you’d configure the endpoint URL like this:

https://${stageVariables.backendEndpoint}/some/resource

And for a header value, you might use:

{"x-api-key": "${stageVariables.apiKey}"}

When a request comes in for the dev stage, API Gateway will dynamically substitute ${stageVariables.backendEndpoint} with https://dev.my-backend.com/v1 and ${stageVariables.apiKey} with dev-api-key-12345 before making the backend call.

This solves the problem of hardcoding environment-specific values directly into your API resources, which is a maintenance nightmare. Instead of creating entirely separate APIs or stages for each environment (which can lead to duplication and drift), you can maintain a single API definition and use stage variables to tweak its behavior.

The mental model here is that your API Gateway definition is a template, and stage variables are parameters you pass to that template at deployment time for a specific stage. Each stage (e.g., dev, staging, prod) can have its own distinct set of stage variables.

To manage these, you can use the AWS CLI:

To get the current stage variables for a stage:

aws apigateway get-stage --rest-api-id abc123xyz --stage-name dev --query 'variables'

To update stage variables for a stage:

aws apigateway update-stage --rest-api-id abc123xyz --stage-name dev --patch-operations '[
  {"op": "replace", "path": "/variables/backendEndpoint", "value": "https://new-dev-endpoint.com/v2"},
  {"op": "add", "path": "/variables/newVariable", "value": "someValue"}
]'

This allows for dynamic configuration changes without redeploying the entire API. When you update a stage variable, API Gateway automatically picks up the changes for subsequent requests to that stage.

The surprising part is how seamlessly these variables can be used not just in integration endpoints but also in request/response mappings, authorizers, and even in defining custom domain names. You can construct complex URLs, dynamically set authorization headers, or conditionally route to different backend services based on these variables.

The next step is to explore how stage variables interact with deployment strategies like canary releases.

Want structured learning?

Take the full Apigateway course →