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

  1. Local dev — environment variables override SSM; developers need no AWS access for non-secret config.
  2. CI — an OIDC role grants ssm:GetParametersByPath on the test path only.
  3. Staging/Production — the pod’s role reads its own /myapp/ prefix with kms: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 SecureString for any sensitive parameter; never String.
  • 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

  • AccessDeniedException on GetParametersByPath — the role lacks the path or kms:Decrypt; scope both.
  • SecureString returned encryptedWithDecryption=True was 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.