Skip to main content

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โ€‹

FeatureSecrets ManagerSSM Parameter Store
Primary useApplication secrets (DB passwords, API keys)Configuration & secrets
Automatic Rotationโœ… Native (RDS, Redshift, DocumentDB, custom)โŒ Manual (custom Lambda)
Cost0.40/secret/month + 0.05/10K API callsFree (Standard), $0.05/advanced/month
Max value size64 KB4 KB (Standard), 8 KB (Advanced)
Cross-accountโœ… Resource policyโŒ Limited
Versioningโœ… (AWSCURRENT, AWSPREVIOUS, AWSPENDING)โœ… (by version number/label)
EncryptionKMS (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โ€‹

DatabaseRotation LambdaManaged By
RDS (MySQL, PostgreSQL, Oracle, SQL Server)AWS-provided templateAWS
AuroraAWS-provided templateAWS
RedshiftAWS-provided templateAWS
DocumentDBAWS-provided templateAWS
Any other (API keys, 3rd-party)Custom Lambda you writeYou

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โ€‹

TypeEncryptionUse Case
StringNoneURLs, feature flags, non-sensitive config
StringListNoneComma-separated values
SecureStringKMS encryptedPasswords, API keys, tokens

Parameter Tiersโ€‹

TierMax SizePoliciesThroughputCost
Standard4 KBโŒ40 TPS (shared)Free
Advanced8 KBโœ… Expiration, notification10,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}}"
CloudFormation + SecureString

You CANNOT use AWS::SSM::Parameter::Value<String> parameter type for SecureString. You MUST use dynamic references {{resolve:ssm-secure:...}}.


Choosing the Right Serviceโ€‹

ScenarioBest ChoiceWhy
RDS password with auto-rotationSecrets ManagerNative rotation support
50 config values, mostly non-sensitiveSSM Parameter StoreFree, hierarchical
API key rotating every 30 daysSecrets ManagerAuto-rotation
Feature flagsSSM Parameter Store (String)Free, simple
Sensitive config, no rotationSSM Parameter Store (SecureString)Free with KMS
Cross-account secret sharingSecrets ManagerResource policies
CloudFormation template valuesSSM Parameter StoreNative integration
Database connection stringsEitherSM if rotation needed, SSM if not

๐ŸŽฏ DVA-C02 Exam Tipsโ€‹

Secrets & Parameters Exam Cheat Sheet
  1. Auto-rotation = Secrets Manager (SSM has no native rotation)
  2. Free storage = SSM Parameter Store Standard
  3. SecureString in CloudFormation = {{resolve:ssm-secure:...}} (NOT parameter type)
  4. Secrets Manager caching = use caching client or Lambda extension
  5. Cross-account = Secrets Manager with resource policy
  6. Reading SecureString needs both ssm:GetParameter AND kms:Decrypt
  7. Lambda extension caches both secrets and parameters locally
  8. Advanced tier supports parameter policies (expiration, notification)
  9. Secret versions: AWSCURRENT (active), AWSPREVIOUS (old), AWSPENDING (rotating)
  10. 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.


๐Ÿ”— Resourcesโ€‹