Skip to content

Environment Variables

Environment Variables decorator is a simple parser for environment variables that run at the start of the handler invocation.

Environment Variables

Key features

  • A defined Pydantic schema for all required environment variables
  • A decorator that parses and validates environment variables, value constraints included
  • Global getter for parsed & valid schema dataclass with all environment variables

The best practice for handling environment variables is to validate & parse them according to a predefined schema as soon as the AWS Lambda function is triggered.

In case of misconfiguration, a validation exception is raised with all the relevant exception details.

Open source

The code in this post has been moved to an open source project you can use:

The AWS Lambda environment variables modeler

Blog Reference

Read more about the importance of validating environment variables and how this utility works. Click HERE

Schema Definition

You need to define all your environment variables in a Pydantic schema class that extend Pydantic's BaseModel class.

For example:

schemas/env_vars.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from typing import Annotated, Literal

from pydantic import BaseModel, Field, HttpUrl


class MyHandlerEnvVars(BaseModel):
    REST_API: HttpUrl
    ROLE_ARN: Annotated[str, Field(min_length=20, max_length=2048)]
    POWERTOOLS_SERVICE_NAME: Annotated[str, Field(min_length=1)]
    LOG_LEVEL: Literal['DEBUG', 'INFO', 'ERROR', 'CRITICAL', 'WARNING', 'EXCEPTION']

All Pydantic schemas extend Pydantic’s ‘BaseModel’ class, turning them into a dataclass.

The schema defines four environment variables: ‘LOG_LEVEL,’ ‘POWERTOOLS_SERVICE_NAME,’ ‘ROLE_ARN,’ and ‘REST_API.’

This schema makes sure that:

  • ‘LOG_LEVEL’ is one of the strings in the Literal list.
  • ‘ROLE_ARN’ exists and is between 20 and 2048 characters long, as defined here.
  • ‘REST_API’ is a valid HTTP URL.
  • ‘POWERTOOLS_SERVICE_NAME’ is a non-empty string.

Read here about Pydantic Model capabilities.

Decorator Usage

The decorator 'init_environment_variables' is defined under the utility folder service.utils.env_vars_parser.py and imported in the handler.

The decorator requires a model parameter, which in this example is the name of the schema class we defined above.

handlers/my_handler.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import json
from http import HTTPStatus
from typing import Any

from aws_lambda_env_modeler import get_environment_variables, init_environment_variables
from aws_lambda_powertools.utilities.typing import LambdaContext

from service.handlers.models.env_vars import MyHandlerEnvVars


@init_environment_variables(model=MyHandlerEnvVars)
def my_handler(event: dict[str, Any], context: LambdaContext) -> dict[str, Any]:
    env_vars = get_environment_variables(model=MyHandlerEnvVars)  # noqa: F841
    return {'statusCode': HTTPStatus.OK, 'headers': {'Content-Type': 'application/json'}, 'body': json.dumps({'message': 'success'})}

Global Getter Usage

The getter function 'get_environment_variables' is defined under the utility folder service.utils.env_vars_parser.py and imported in the handler.

The getter function returns a parsed and validated global instance of the environment variables Pydantic schema class.

It can be used anywhere in the function code, not just the handler.

handlers/my_handler.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import json
from http import HTTPStatus
from typing import Any

from aws_lambda_env_modeler import get_environment_variables, init_environment_variables
from aws_lambda_powertools.utilities.typing import LambdaContext

from service.handlers.models.env_vars import MyHandlerEnvVars


@init_environment_variables(model=MyHandlerEnvVars)
def my_handler(event: dict[str, Any], context: LambdaContext) -> dict[str, Any]:
    env_vars: MyHandlerEnvVars = get_environment_variables(model=MyHandlerEnvVars)  # noqa: F841
    return {'statusCode': HTTPStatus.OK, 'headers': {'Content-Type': 'application/json'}, 'body': json.dumps({'message': 'success'})}

More Details

Read here about Pydantic field types.

Read here about custom validators and advanced value constraints.