Secrets & Config the Grown-Up Way
SSM Parameter Store for plain config, Secrets Manager for rotating credentials β never a secret baked into an image or committed to Git.
Config falls into two buckets, and mixing them up is a classic junior mistake. Non-sensitive settings (feature flags, region, log level) and secrets (DB passwords, API keys, signing keys) want different homes.
Pick the right store
| Need | Use | Why |
|---|---|---|
| Plain config, hierarchical | SSM Parameter Store (String) | Free tier, versioned, great for /app/prod/* trees. |
| Encrypted secret, cheap | SSM SecureString | KMS-encrypted, no rotation machinery. |
| Rotating credential | Secrets Manager | Built-in rotation (esp. RDS), cross-region replication. |
The habits that matter
- Reference, never embed. ECS task defs and Lambda pull secrets by ARN at start-up; the value never touches your image or your repo.
- Scope the read. The execution role reads only its own
/app/prod/*path β not the whole account. - Namespace by environment.
/myapp/staging/db-urlvs/myapp/prod/db-urlkeeps a staging mistake away from prod.
Example
# Store plain config in SSM (versioned, hierarchical)
aws ssm put-parameter \
--name /myapp/prod/LOG_LEVEL \
--type String --value info --overwrite
# Store an encrypted secret
aws ssm put-parameter \
--name /myapp/prod/DB_PASSWORD \
--type SecureString --value 's3cr3t' --overwrite
# Create a rotating secret in Secrets Manager and turn on rotation
aws secretsmanager create-secret \
--name myapp/prod/db-credentials \
--secret-string '{"username":"app","password":"s3cr3t"}'
aws secretsmanager rotate-secret \
--secret-id myapp/prod/db-credentials \
--rotation-rules '{"AutomaticallyAfterDays": 30}'When to use it
- A team stores the database password in Secrets Manager with auto-rotation and reads it via ARN in the ECS task definition, so the secret is never in plaintext anywhere.
- An ops engineer puts all non-secret config (log level, feature flags, API endpoints) in SSM Parameter Store and reads them by path at container startup.
- A security review finds no secrets in Docker images, environment files, or Git history because the team exclusively uses Secrets Manager and SSM.
More examples
SSM for config, Secrets Manager for creds
Demonstrates the split: non-sensitive config in SSM Parameter Store, secrets in Secrets Manager for the rotation and audit trail.
# Plain config in SSM
aws ssm put-parameter --name '/prod/app/log-level' \
--value 'info' --type String --overwrite
# Credentials in Secrets Manager
aws secretsmanager create-secret \
--name 'prod/app/stripe-key' \
--secret-string 'sk_live_abc123'Inject both into ECS task definition
Mixes a plain env var with secrets pulled from Secrets Manager and SSM Parameter Store, keeping the task definition clean.
{
"environment": [
{ "name": "LOG_LEVEL",
"value": "info" }
],
"secrets": [
{ "name": "STRIPE_KEY",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/app/stripe-key" },
{ "name": "DB_URL",
"valueFrom": "/prod/app/db-url" }
]
}Scan for hardcoded secrets in repo
Runs a secret-scanning tool across the repository to catch accidentally committed credentials before they reach CI or GitHub.
# Use git-secrets or trufflehog to catch leaks before push
git secrets --scan
# Or with trufflehog:
trufflehog git file://. --only-verified
Discussion