You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Lazy loading defers field value resolution until fields are actually accessed, rather than eagerly fetching all values during settings initialization. This is particularly useful when working with cloud secret managers where each field access triggers an API call, avoiding unnecessary network requests for fields that may never be used.
2939
+
2940
+
### Overview
2941
+
2942
+
By default, pydantic-settings eagerly resolves all field values from all configured sources during initialization. For cloud secret managers like AWS Secrets Manager, Azure Key Vault, or Google Cloud Secret Manager, this means every field triggers an API call to fetch the secret value, even if the application never uses that field.
2943
+
2944
+
**When to use lazy loading:**
2945
+
2946
+
* You use cloud secret managers (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager)
2947
+
* Your settings have many fields but your application only uses a subset of them
2948
+
* You want to reduce initialization time and API call costs
2949
+
* Network latency to secret managers is significant
2950
+
2951
+
**Trade-offs:**
2952
+
2953
+
* Fields are resolved when first accessed, not during initialization, so errors surface later
2954
+
* There's a small overhead on first access to each field (caching minimizes subsequent accesses)
2955
+
*`model_dump()` and other full-model operations will trigger resolution of all fields
2956
+
2957
+
### Basic Usage
2958
+
2959
+
You can enable lazy loading in two ways:
2960
+
2961
+
**1. Global configuration via SettingsConfigDict:**
2962
+
2963
+
```py
2964
+
from pydantic_settings import BaseSettings, SettingsConfigDict
2965
+
2966
+
2967
+
classSettings(BaseSettings):
2968
+
model_config = SettingsConfigDict(lazy_load=True)
2969
+
2970
+
api_key: str
2971
+
database_url: str
2972
+
debug_mode: bool
2973
+
```
2974
+
2975
+
**2. Per-source configuration via settings_customise_sources:**
2976
+
2977
+
```py
2978
+
import os
2979
+
2980
+
from pydantic_settings import (
2981
+
AWSSecretsManagerSettingsSource,
2982
+
BaseSettings,
2983
+
PydanticBaseSettingsSource,
2984
+
)
2985
+
2986
+
2987
+
classSettings(BaseSettings):
2988
+
api_key: str
2989
+
database_url: str
2990
+
2991
+
@classmethod
2992
+
defsettings_customise_sources(
2993
+
cls,
2994
+
settings_cls: type[BaseSettings],
2995
+
init_settings: PydanticBaseSettingsSource,
2996
+
env_settings: PydanticBaseSettingsSource,
2997
+
dotenv_settings: PydanticBaseSettingsSource,
2998
+
file_secret_settings: PydanticBaseSettingsSource,
2999
+
) -> tuple[PydanticBaseSettingsSource, ...]:
3000
+
aws_settings = AWSSecretsManagerSettingsSource(
3001
+
settings_cls,
3002
+
secret_id=os.environ['AWS_SECRET_ID'],
3003
+
lazy_load=True, # Enable lazy loading only for AWS Secrets Manager
3004
+
)
3005
+
return (
3006
+
init_settings,
3007
+
env_settings,
3008
+
dotenv_settings,
3009
+
aws_settings,
3010
+
file_secret_settings,
3011
+
)
3012
+
```
3013
+
3014
+
### Cloud Secret Managers with Lazy Loading
3015
+
3016
+
Lazy loading provides significant performance benefits when using cloud secret managers. Here are examples for each provider:
3017
+
3018
+
#### AWS Secrets Manager
3019
+
3020
+
```py
3021
+
import os
3022
+
from unittest.mock import MagicMock, patch
3023
+
3024
+
from pydantic import Field
3025
+
3026
+
from pydantic_settings import (
3027
+
AWSSecretsManagerSettingsSource,
3028
+
BaseSettings,
3029
+
PydanticBaseSettingsSource,
3030
+
)
3031
+
3032
+
3033
+
classSettings(BaseSettings):
3034
+
# These fields will only be fetched from AWS Secrets Manager when accessed
# First access would trigger GCP Secret Manager API call (in production)
3174
+
# settings.api_key
3175
+
```
3176
+
3177
+
### Behavior and Caching
3178
+
3179
+
When lazy loading is enabled:
3180
+
3181
+
1.**Initialization**: Settings are created with minimal overhead. Sources return empty dictionaries instead of eagerly fetching all values.
3182
+
3183
+
2.**First Access**: When you access a field for the first time (e.g., `settings.api_key`), the value is fetched from the configured source and cached in memory.
3184
+
3185
+
3.**Subsequent Access**: Accessing the same field again returns the cached value without making another API call.
3186
+
3187
+
4.**All Fields**: Iteration over all fields (via `model_dump()`, etc.) will trigger resolution of all fields at once.
0 commit comments