Secrets Manager & SSM
AWS Secrets Manager stores rotatable secrets; SSM Parameter Store holds configuration and secure strings. Python apps fetch values at startup or on cache miss with boto3 instead of baking credentials into images.
Search across all documentation pages
AWS Secrets Manager stores rotatable secrets; SSM Parameter Store holds configuration and secure strings. Python apps fetch values at startup or on cache miss with boto3 instead of baking credentials into images.
import boto3
sm = boto3.client("secretsmanager")
resp = sm.get_secret_value(SecretId="prod/db/password")
password = resp["SecretString"]When to reach for this:
String)SecureString) with KMS encryptionFetch secret JSON, parse fields, and read SSM parameters with caching.
import json
import time
from typing import Any
import boto3
class SecretCache:
def __init__(self, ttl_seconds: int = 300) -> None:
self._ttl = ttl_seconds
self._cache: dict[str, tuple[float, Any]] = {}
self._sm = boto3.client("secretsmanager")
self._ssm = boto3.client("ssm")
def get_secret_json(self, secret_id: str) -> dict:
now = time.monotonic()
if secret_id in self._cache:
expires, value = self._cache[secret_id]
if now < expires:
return value
resp = self._sm.get_secret_value(SecretId=secret_id)
data = json.loads(resp["SecretString"])
self._cache[secret_id] = (now + self._ttl, data)
return data
def get_parameter(self, name: str, decrypt: bool = True) -> str:
resp = self._ssm.get_parameter(Name=name, WithDecryption=decrypt)
return resp["Parameter"]["Value"]
if __name__ == "__main__":
cache = SecretCache()
creds = cache.get_secret_json("app/database")
print(creds.get("username"))
region = cache.get_parameter("/app/region")
print(region)What this demonstrates:
SecretString often contains JSON - parse once and cache in memory/app/region) organize parameters by service| Feature | Secrets Manager | SSM Parameter Store |
|---|---|---|
| Rotation | Built-in lambdas | Manual/custom |
| Cost | Higher per secret | Cheaper for plain config |
| Use case | DB passwords, API keys | Feature flags, URLs |
secretsmanager:GetSecretValue or ssm:GetParameter on specific ARNsSecureString and many secretsfrom botocore.exceptions import ClientError
def get_secret_or_none(secret_id: str) -> str | None:
try:
return boto3.client("secretsmanager").get_secret_value(SecretId=secret_id)["SecretString"]
except ClientError as exc:
if exc.response["Error"]["Code"] == "ResourceNotFoundException":
return None
raise/app/${ENV}/db paths.secretsmanager:* on *. Fix: ARN-level policies per secret.| Alternative | Use When | Don't Use When |
|---|---|---|
| HashiCorp Vault | Multi-cloud secret platform | Simple AWS-only stack |
| K8s secrets | Kubernetes-native deploy | Plain EC2/Lambda without sealed secrets |
| Env vars from CI | Ephemeral deploy-time injection | Apps need runtime rotation |
Secrets Manager for credentials needing rotation; SSM SecureString for static secrets and config with KMS.
Reference secret ARN in env var; Lambda resolves at init, or fetch in code with cache.
Custom settings source that calls boto3 on first access, then caches - keeps validation in one place.
Inject fake SecretCache in tests; moto supports basic secretsmanager mocks.
.env excluded from git for laptops; production uses Secrets Manager/SSM only.
get_parameters_by_path loads /app/prod/* in one call for bootstrap config.
IAM must allow both ssm:GetParameter and kms:Decrypt on the CMK used by the parameter.
Plan brief dual-password window in DB or app retry on auth failure during rotation event.
Acceptable when injected at container start from secret reference - not when baked into image layers.
CloudTrail logs GetSecretValue calls - alert on unusual principals or regions.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026