AWS Lambda environment variables let you pass configuration to your function without modifying code or redeploying artifacts. They are available as standard OS-level environment variables at runtime, accessible through process.env in Node.js or os.environ in Python. Lambda encrypts environment variables at rest with AWS KMS by default, but sensitive values like database credentials and API keys deserve additional protection via customer-managed KMS keys, AWS Secrets Manager, or Parameter Store. This guide covers every way to set, manage, and secure environment variables in Lambda across the Console, CLI, SAM, CDK, and Terraform.
How do you set environment variables in the AWS Console?
Open your function in the Lambda console, select the Configuration tab, then Environment variables. Click Edit, add key-value pairs, and save. Each save creates a new function version. Variables are available immediately on the next invocation.
The console is useful for quick changes and debugging, but infrastructure-as-code is the recommended approach for production workloads. Manual console changes are not tracked in version control and will be overwritten by your next IaC deployment.
How do you set environment variables with the AWS CLI?
Use aws lambda update-function-configuration to set or update environment variables from the command line. The --environment flag replaces all existing variables, so always include every variable you want to keep.
# Set environment variables (replaces all existing ones)
aws lambda update-function-configuration \
--function-name my-function \
--environment '{"Variables":{"NODE_ENV":"production","DATABASE_URL":"postgres://db:5432/app","LOG_LEVEL":"info"}}'
# Read current environment variables
aws lambda get-function-configuration \
--function-name my-function \
--query "Environment.Variables"To update a single variable without losing others, fetch the current configuration first, merge your change, and push the full set back. Alternatively, use a wrapper script or a tool like jq to automate this.
How do you define environment variables in SAM templates?
In AWS SAM, environment variables are declared under the Environment.Variables property of your function resource. SAM supports parameter references and intrinsic functions for dynamic values.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
Stage:
Type: String
Default: dev
Globals:
Function:
Runtime: nodejs22.x
Timeout: 30
Environment:
Variables:
STAGE: !Ref Stage
LOG_LEVEL: info
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
CodeUri: ./src
Environment:
Variables:
DATABASE_URL: !Sub "postgres://${Stage}-db.example.com:5432/app"
FEATURE_NEW_UI: "true"Variables defined in Globals.Function.Environment apply to every function in the template. Function-level variables are merged in, with function-level values taking precedence on conflicts.
How do you set environment variables in AWS CDK?
CDK provides the environment property on Lambda function constructs in both TypeScript and Python.
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
export class MyStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_22_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
environment: {
NODE_ENV: 'production',
DATABASE_URL: 'postgres://db.example.com:5432/app',
LOG_LEVEL: 'warn',
},
});
// Add a single variable after construction
fn.addEnvironment('FEATURE_FLAG', 'true');
}
}The equivalent in Python CDK:
from aws_cdk import Stack
from aws_cdk import aws_lambda as _lambda
from constructs import Construct
class MyStack(Stack):
def __init__(self, scope: Construct, id: str, **kwargs):
super().__init__(scope, id, **kwargs)
fn = _lambda.Function(
self, "MyFunction",
runtime=_lambda.Runtime.PYTHON_3_13,
handler="index.handler",
code=_lambda.Code.from_asset("lambda"),
environment={
"DATABASE_URL": "postgres://db.example.com:5432/app",
"LOG_LEVEL": "warn",
},
)
fn.add_environment("FEATURE_FLAG", "true")How do you configure environment variables in Terraform?
In Terraform, environment variables go inside the environment block of an aws_lambda_function resource. See our Terraform variables guide for more on Terraform variable management.
variable "environment" {
type = string
default = "dev"
}
resource "aws_lambda_function" "api" {
function_name = "my-api-${var.environment}"
runtime = "nodejs22.x"
handler = "index.handler"
filename = "lambda.zip"
role = aws_iam_role.lambda_exec.arn
environment {
variables = {
NODE_ENV = var.environment
DATABASE_URL = var.database_url
LOG_LEVEL = "info"
}
}
}Terraform tracks the environment variable state, so removing a variable from the variables map and running terraform apply will delete it from the function.
What are the reserved Lambda environment variables?
Lambda sets several environment variables automatically. You cannot override these — attempts to set them will cause a deployment error.
| Variable | Description |
|---|---|
| AWS_LAMBDA_FUNCTION_NAME | Name of the function |
| AWS_LAMBDA_FUNCTION_VERSION | Published version being executed |
| AWS_LAMBDA_FUNCTION_MEMORY_SIZE | Memory allocated in MB |
| AWS_REGION | Region the function runs in |
| AWS_LAMBDA_LOG_GROUP_NAME | CloudWatch log group name |
| AWS_LAMBDA_LOG_STREAM_NAME | CloudWatch log stream for the invocation |
| _HANDLER | Handler location configured for the function |
| AWS_EXECUTION_ENV | Runtime identifier (e.g. AWS_Lambda_nodejs22.x) |
Any variable prefixed with AWS_ is reserved. Avoid using this prefix for your own variables.
How do you encrypt sensitive variables with KMS?
Lambda encrypts all environment variables at rest with a default AWS-managed KMS key. For sensitive values, use a customer-managed KMS key and enable encryption helpers in the console, or configure it in your IaC. With a customer-managed key, you control key rotation and access policies independently from Lambda permissions.
# SAM template with customer-managed KMS key
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs22.x
CodeUri: ./src
KmsKeyArn: arn:aws:kms:us-east-1:123456789012:key/abcd-1234
Environment:
Variables:
DB_PASSWORD: "AQICAHh...encrypted-blob..."
API_SECRET: "AQICAHh...encrypted-blob..."When using encrypted values, your function code must decrypt them at runtime using the KMS SDK:
import { KMSClient, DecryptCommand } from '@aws-sdk/client-kms';
const kms = new KMSClient({});
async function decrypt(encrypted: string): Promise<string> {
const { Plaintext } = await kms.send(
new DecryptCommand({ CiphertextBlob: Buffer.from(encrypted, 'base64') })
);
return Buffer.from(Plaintext!).toString('utf-8');
}
// Decrypt once during cold start, cache the result
const dbPassword = await decrypt(process.env.DB_PASSWORD!);When should you use Secrets Manager or Parameter Store instead?
Environment variables are baked into the function configuration. Changing them requires a configuration update and a new cold start. For values that rotate frequently (database credentials, API tokens), use AWS Secrets Manager or SSM Parameter Store and fetch at runtime. This decouples secret rotation from deployments. See our guide on sharing env files securely for cross-team patterns that pair well with Secrets Manager.
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
const sm = new SecretsManagerClient({});
// Cache outside the handler for reuse across warm invocations
let cachedSecret: string | undefined;
export async function handler() {
if (!cachedSecret) {
const { SecretString } = await sm.send(
new GetSecretValueCommand({ SecretId: process.env.SECRET_ARN })
);
cachedSecret = SecretString;
}
const { username, password } = JSON.parse(cachedSecret!);
// Use credentials...
}Store the secret ARN or parameter name in an environment variable, then resolve the actual value at runtime. This way your IaC tracks which secret the function uses without embedding the secret itself.
import boto3
import os
import json
ssm = boto3.client('ssm')
# Fetch from Parameter Store at cold start
param = ssm.get_parameter(
Name=os.environ['DB_CONNECTION_PARAM'],
WithDecryption=True
)
db_config = json.loads(param['Parameter']['Value'])Can Lambda Layers share configuration across functions?
Lambda Layers are primarily for sharing code and dependencies, not configuration. Layers are immutable and versioned — they cannot be changed without publishing a new version. For shared configuration, use environment variables per function, or centralize values in Parameter Store / Secrets Manager. Layers are appropriate for shared utility code that reads configuration, such as a common database connection module.
What are the size limits for environment variables?
Lambda enforces a 4 KB total limit for all environment variables combined. This includes both keys and values. If you exceed this limit, the deployment will fail. Strategies to stay within the limit:
- Move large values (certificates, JSON configs) to S3 or Parameter Store
- Store connection strings and credentials in Secrets Manager
- Use short, descriptive keys — avoid verbose prefixes
- Reference ARNs or parameter names instead of full values
Use our env validator to check the total size of your environment variables before deploying.
AWS_ prefix is reserved for runtime-injected variables — Lambda rejects any user-defined key that starts with AWS_ at deploy time. Move oversized blobs to S3 or Parameter Store and prefix your own variables with something project- or service-specific (e.g. APP_, SVC_).What are common patterns for Lambda environment variables?
Most Lambda functions need a combination of feature flags, service endpoints, and connection strings. Establish a naming convention early and apply it consistently.
# Feature flags
FEATURE_NEW_CHECKOUT=true
FEATURE_DARK_MODE=false
# API endpoints
PAYMENT_API_URL=https://api.stripe.com/v1
NOTIFICATION_SERVICE_URL=https://notify.internal.example.com
# Database connections
DATABASE_URL=postgres://user:pass@db.example.com:5432/app
REDIS_URL=redis://cache.example.com:6379
# Operational config
LOG_LEVEL=info
TIMEOUT_MS=5000
MAX_RETRIES=3Prefix variables by concern (FEATURE_, DB_, API_) for readability. Avoid putting secrets directly in environment variables for production — use Secrets Manager references and resolve at runtime. For non-sensitive values like feature flags and endpoints, environment variables are the simplest and most performant option since they require no network calls at startup.