AWS Secrets Manager stores, rotates, and retrieves secrets — database credentials, API keys, OAuth tokens — via a managed service with IAM-governed access and KMS encryption. It removes the need to check secrets into code or configuration, and makes credential rotation an automated, auditable process.
GetSecretValue is logged to CloudTrail for access auditing.GetSecretValue/sec and 50 administrative calls/sec per account per region (soft).GetSecretValue on every request instead of caching — at high QPS this dwarfs the per-secret cost. Use the AWS-provided caching client or Secrets Manager Lambda Extension.
import boto3, json
from aws_secretsmanager_caching import SecretCache, SecretCacheConfig
client = boto3.client("secretsmanager", region_name="us-west-2")
cache = SecretCache(
config=SecretCacheConfig(secret_refresh_interval=3600),
client=client,
)
def db_creds():
raw = cache.get_secret_string("prod/app/db")
return json.loads(raw)
# {"username": "app", "password": "...", "host": "...", "port": 5432}
# First call hits Secrets Manager; subsequent calls return cached value.
creds = db_creds()
aws secretsmanager create-secret \
--name prod/app/db \
--description "Postgres app user" \
--secret-string '{"username":"app","password":"REPLACE-ME"}' \
--kms-key-id alias/secrets
aws secretsmanager rotate-secret \
--secret-id prod/app/db \
--rotation-lambda-arn arn:aws:lambda:us-west-2:111122223333:function:RotateRDSPostgres \
--rotation-rules AutomaticallyAfterDays=30
The rotation Lambda runs four phases: createSecret generates a new password and stages it under the AWSPENDING label; setSecret updates the database with the new credential; testSecret verifies it works; finishSecret moves the AWSCURRENT label to the new version and demotes the previous one to AWSPREVIOUS. Applications always request AWSCURRENT and rollback is one label move away.
Non-sensitive config (feature flags, regional endpoints), or sensitive values where you don't need rotation and the cost of $0.40/secret/month at scale matters. Parameter Store standard tier is free; advanced is $0.05/parameter/month.
Use a customer-managed KMS key (AWS-managed keys can't grant external access), attach a resource policy to the secret allowing the consumer account principal, and grant the consumer's KMS key policy decrypt rights. The consumer then calls GetSecretValue across accounts.
Fetch outside the handler so the value is reused across warm invocations, and either set a TTL refresh or use the Secrets Manager Lambda Extension that runs as a local HTTP cache. Never call GetSecretValue on every request — it adds latency and dominates cost.
Only with --force-delete-without-recovery, which bypasses the 7-30 day recovery window. Default deletion is recoverable so a typo or compromised admin can't permanently destroy production credentials.
The AWSPENDING label remains attached to the staged version but AWSCURRENT is unchanged, so applications keep working with the old credential. CloudWatch alarms on the rotation Lambda errors are essential — silent rotation failures can let credentials expire if the database has independent password expiry.