Settings from AWS Parameter Store
AWS Systems Manager Parameter Store is the cheap, IAM-scoped place to keep configuration and modest secrets — but pydantic-settings does not read it out of the box. This page adds Parameter Store as a first-class settings source so SSM parameters validate through the same model as everything else. It builds on type-safe validation with pydantic-settings alongside pydantic-settings fundamentals.
Secure implementation
# config/ssm_source.py
import boto3
from pydantic import SecretStr
from pydantic_settings import (
BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict,
)
class SSMSource(PydanticBaseSettingsSource):
"""Reads a path prefix from SSM Parameter Store, decrypting SecureStrings."""
def __call__(self) -> dict[str, object]:
ssm = boto3.client("ssm")
out: dict[str, object] = {}
paginator = ssm.get_paginator("get_parameters_by_path")
for page in paginator.paginate(Path="/myapp/", Recursive=True, WithDecryption=True):
for p in page["Parameters"]:
key = p["Name"].rsplit("/", 1)[-1].lower()
out[key] = p["Value"]
return out
def get_field_value(self, field, field_name): # required abstract hook
return None, field_name, False
class Settings(BaseSettings):
model_config = SettingsConfigDict(extra="forbid")
database_url: str
api_key: SecretStr
@classmethod
def settings_customise_sources(cls, settings_cls, init_settings,
env_settings, dotenv_settings, file_secret_settings):
# env vars still win; SSM sits below them for parity.
return (init_settings, env_settings, SSMSource(settings_cls), dotenv_settings)
WithDecryption=True resolves SecureString parameters; the model validates them like any other source, and environment variables still take precedence for local overrides. Secret fields are typed SecretStr.
Configuration reference
| Element | Type | Notes | Security implication |
|---|---|---|---|
get_parameters_by_path |
SSM API | Paginated, recursive | Scope IAM to the path prefix |
WithDecryption=True |
bool | Decrypts SecureString |
Needs kms:Decrypt on the key |
SecureString |
param type | KMS-encrypted | Use for secrets, not String |
SecretStr field |
masked | — | Keeps decrypted value out of logs |
| custom source order | tuple | Env above SSM | Local overrides win for parity |
Step-by-step deployment parity
- Local dev — environment variables override SSM; developers need no AWS access for non-secret config.
- CI — an OIDC role grants
ssm:GetParametersByPathon the test path only. - Staging/Production — the pod’s role reads its own
/myapp/prefix withkms:Decrypt; the same model validates the result.
Security boundaries & operational guardrails
- IAM scoped to the exact parameter path prefix and KMS key — no wildcards.
- Use
SecureStringfor any sensitive parameter; neverString. - Wrap decrypted secrets in
SecretStr; unwrap only at the point of use. - Keep
extra="forbid"so an unexpected parameter fails validation. - Cache parameters in memory with a TTL to stay within SSM throughput limits.
Troubleshooting
AccessDeniedExceptiononGetParametersByPath— the role lacks the path orkms:Decrypt; scope both.SecureStringreturned encrypted —WithDecryption=Truewas omitted.- Throttled at scale — add the in-memory TTL cache. See Cache Parameter Store Values to Reduce API Calls.
- Env var ignored — that is correct; env sits above SSM in the source order.
Frequently asked questions
How do I load pydantic-settings from AWS Parameter Store?
Implement a custom settings source by subclassing PydanticBaseSettingsSource and override settings_customise_sources to add it. The source calls get_parameters_by_path and returns a dict the model validates like any other source.
What is the difference between Parameter Store and Secrets Manager?
Parameter Store is cheaper and good for configuration plus modest secrets via SecureString; Secrets Manager adds native rotation and higher throughput. Use Parameter Store for config and small secret sets, Secrets Manager when you need built-in rotation.
Should Parameter Store values be cached?
Yes. SSM has per-account throughput limits, so cache fetched parameters in memory with a short TTL and wrap SecureString values in SecretStr.
Conclusion
The invariant: Parameter Store is just another validated source below the environment, with SecureString for secrets and SecretStr in the model. Configuration and modest secrets share one cheap, IAM-scoped store.