Secrets Manager vs SSM Parameter Store
Exam hook: These two services overlap โ the exam tests your ability to choose the right one for each scenario.
๐ฐ When to Use Which?โ
Quick rule: Need automatic rotation for database credentials? โ Secrets Manager. Need cheap configuration storage? โ SSM Parameter Store.
Side-by-Side Comparisonโ
| Feature | Secrets Manager | SSM Parameter Store |
|---|---|---|
| Primary use | Application secrets (DB passwords, API keys) | Configuration & secrets |
| Automatic Rotation | โ Native (RDS, Redshift, DocumentDB, custom) | โ Manual (custom Lambda) |
| Cost | 0.40/secret/month + 0.05/10K API calls | Free (Standard), $0.05/advanced/month |
| Max value size | 64 KB | 4 KB (Standard), 8 KB (Advanced) |
| Cross-account | โ Resource policy | โ Limited |
| Versioning | โ (AWSCURRENT, AWSPREVIOUS, AWSPENDING) | โ (by version number/label) |
| Encryption | KMS (always encrypted) | Optional KMS (SecureString) |
| CloudFormation | {{resolve:secretsmanager:...}} | {{resolve:ssm:...}} |
| Lambda Extension | โ Caching extension available | โ Same extension |
Secrets Manager Deep Diveโ
Secret Rotation Lifecycleโ
1. createSecret โ Generate new credentials (AWSPENDING stage)
2. setSecret โ Update database with new credentials
3. testSecret โ Verify new credentials work against database
4. finishSecret โ Promote AWSPENDING โ AWSCURRENT
Demote old AWSCURRENT โ AWSPREVIOUS
Supported Auto-Rotationโ
| Database | Rotation Lambda | Managed By |
|---|---|---|
| RDS (MySQL, PostgreSQL, Oracle, SQL Server) | AWS-provided template | AWS |
| Aurora | AWS-provided template | AWS |
| Redshift | AWS-provided template | AWS |
| DocumentDB | AWS-provided template | AWS |
| Any other (API keys, 3rd-party) | Custom Lambda you write | You |
Java โ Reading Secretsโ
// Static init โ cache at INIT time (runs once per cold start)
private static final SecretsManagerClient smClient = SecretsManagerClient.create();
private static final ObjectMapper mapper = new ObjectMapper();
private static final DbConfig DB_CONFIG;
static {
String secretString = smClient.getSecretValue(GetSecretValueRequest.builder()
.secretId("prod/myapp/db-credentials")
.build())
.secretString();
DB_CONFIG = mapper.readValue(secretString, DbConfig.class);
}
// Handler uses cached DB_CONFIG โ no API call on warm invocations
public String handleRequest(Object event, Context context) {
Connection conn = DriverManager.getConnection(
DB_CONFIG.getHost(), DB_CONFIG.getUsername(), DB_CONFIG.getPassword());
// ...
}
Secrets Manager Caching Clientโ
// Reduces API calls by caching secrets in memory with TTL
// Dependency: software.amazon.awssdk:aws-secretsmanager-caching-java
SecretCache cache = new SecretCache(
SecretCacheConfiguration.builder()
.maxCacheSize(1000)
.expiryInMs(300_000) // 5 minutes
.build());
String secretString = cache.getSecretString("prod/myapp/db-credentials");
AWS Parameters and Secrets Lambda Extensionโ
# No SDK code needed! Use localhost HTTP endpoint
# Add the extension layer
MyFunction:
Type: AWS::Serverless::Function
Properties:
Layers:
- arn:aws:lambda:us-east-1:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11
Environment:
Variables:
SECRETS_MANAGER_TTL: 300 # Cache for 5 minutes
// Read secret via HTTP (uses extension's local cache)
HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(
HttpRequest.newBuilder()
.uri(URI.create("http://localhost:2773/secretsmanager/get?secretId=prod/myapp/db-credentials"))
.header("X-Aws-Parameters-Secrets-Token", System.getenv("AWS_SESSION_TOKEN"))
.build(),
HttpResponse.BodyHandlers.ofString());
Cross-Account Secret Sharingโ
// Secret resource policy allowing another account
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::987654321098:role/AppRole" },
"Action": ["secretsmanager:GetSecretValue"],
"Resource": "*"
}
SSM Parameter Store Deep Diveโ
Parameter Typesโ
| Type | Encryption | Use Case |
|---|---|---|
String | None | URLs, feature flags, non-sensitive config |
StringList | None | Comma-separated values |
SecureString | KMS encrypted | Passwords, API keys, tokens |
Parameter Tiersโ
| Tier | Max Size | Policies | Throughput | Cost |
|---|---|---|---|---|
| Standard | 4 KB | โ | 40 TPS (shared) | Free |
| Advanced | 8 KB | โ Expiration, notification | 10,000 TPS | $0.05/month |
Hierarchical Namingโ
/prod/myapp/db-url โ String
/prod/myapp/db-password โ SecureString
/prod/myapp/feature-flags โ StringList
/dev/myapp/db-url โ String
/shared/certificates/ssl โ SecureString
// Get all parameters under a path
GetParametersByPathResponse response = ssmClient.getParametersByPath(
GetParametersByPathRequest.builder()
.path("/prod/myapp/")
.withDecryption(true)
.recursive(true)
.build());
response.parameters().forEach(p ->
System.out.println(p.name() + " = " + p.value()));
Parameter Policies (Advanced Tier)โ
[
{
"Type": "Expiration",
"Version": "1.0",
"Attributes": { "Timestamp": "2025-12-31T00:00:00.000Z" }
},
{
"Type": "ExpirationNotification",
"Version": "1.0",
"Attributes": { "Before": "15", "Unit": "Days" }
},
{
"Type": "NoChangeNotification",
"Version": "1.0",
"Attributes": { "After": "90", "Unit": "Days" }
}
]
CloudFormation Dynamic Referencesโ
# SSM String/StringList
MasterUserPassword: "{{resolve:ssm:/prod/myapp/db-url}}"
# SSM SecureString (MUST use ssm-secure)
MasterUserPassword: "{{resolve:ssm-secure:/prod/myapp/db-password:1}}"
# Secrets Manager
MasterUserPassword: "{{resolve:secretsmanager:prod/myapp/db-creds:SecretString:password}}"
You CANNOT use AWS::SSM::Parameter::Value<String> parameter type for SecureString. You MUST use dynamic references {{resolve:ssm-secure:...}}.
Choosing the Right Serviceโ
| Scenario | Best Choice | Why |
|---|---|---|
| RDS password with auto-rotation | Secrets Manager | Native rotation support |
| 50 config values, mostly non-sensitive | SSM Parameter Store | Free, hierarchical |
| API key rotating every 30 days | Secrets Manager | Auto-rotation |
| Feature flags | SSM Parameter Store (String) | Free, simple |
| Sensitive config, no rotation | SSM Parameter Store (SecureString) | Free with KMS |
| Cross-account secret sharing | Secrets Manager | Resource policies |
| CloudFormation template values | SSM Parameter Store | Native integration |
| Database connection strings | Either | SM if rotation needed, SSM if not |
๐ฏ DVA-C02 Exam Tipsโ
- Auto-rotation = Secrets Manager (SSM has no native rotation)
- Free storage = SSM Parameter Store Standard
- SecureString in CloudFormation =
{{resolve:ssm-secure:...}}(NOT parameter type) - Secrets Manager caching = use caching client or Lambda extension
- Cross-account = Secrets Manager with resource policy
- Reading SecureString needs both
ssm:GetParameterANDkms:Decrypt - Lambda extension caches both secrets and parameters locally
- Advanced tier supports parameter policies (expiration, notification)
- Secret versions: AWSCURRENT (active), AWSPREVIOUS (old), AWSPENDING (rotating)
- Cost: $0.40/secret/month (SM) vs Free (SSM Standard)
๐งช Practice Questionsโ
Q1. RDS password with automatic 30-day rotation. Best service?
A) SSM Parameter Store (SecureString)
B) Secrets Manager
C) KMS encrypted env variable
D) S3 encrypted file
โ Answer & Explanation
B โ Secrets Manager has native rotation for RDS with AWS-provided Lambda templates.
Q2. 50 config values, mostly non-sensitive. Most cost-effective?
A) Secrets Manager (one per value)
B) SSM Parameter Store (String + SecureString)
C) Environment variables
D) S3 config file
โ Answer & Explanation
B โ SSM Standard is free. 50 secrets in Secrets Manager = $20/month. Use String for non-sensitive, SecureString for sensitive.
Q3. Lambda reads DB secret every invocation โ high API costs. Best fix?
A) Cache in DynamoDB
B) Secrets Manager caching client or Lambda extension
C) Store in env variable
D) Read only in cold start
โ Answer & Explanation
B โ Caching client caches in memory with TTL. Lambda extension provides HTTP-based caching at localhost:2773. Both reduce API calls dramatically.
Q4. CloudFormation needs SecureString from SSM. How to reference?
A) AWS::SSM::Parameter::Value<SecureString>
B) {{resolve:ssm-secure:/path/to/param}}
C) Direct parameter section default
D) Custom resource Lambda
โ Answer & Explanation
B โ SecureString MUST use dynamic references. The Parameters section doesn't support SecureString type.