AWS SSM Parameter Store

Updated 5 min read index source
On this page9
  1. Parameter types
  2. Standard vs Advanced tier
  3. Hierarchical organization
  4. Parameter Store vs Secrets Manager
  5. Reading parameters in an app
  6. Versioning
  7. EnvVar injection in ECS / Lambda
  8. Common gotchas
  9. Interview angle

AWS SSM Parameter Store

Hierarchical config + secret storage. Part of AWS Systems Manager. The cheaper, simpler sibling of Secrets Manager — and “which one do I use?” is a guaranteed interview question.

Parameter types

Type Encrypted? Use for
String no plain config — feature flags, URLs, log levels
StringList no comma-separated lists
SecureString yes (KMS) secrets — passwords, API keys, tokens

SecureString encrypts the value with KMS (default aws/ssm key or a customer-managed key). Reading it requires both ssm:GetParameter and kms:Decrypt on the key.

Standard vs Advanced tier

Standard Advanced
Cost free ~$0.05 per parameter / month
Max value size 4 KB 8 KB
Parameters per account 10,000 100,000
Parameter policies (expiration, notifications) no yes
Higher throughput shared optional higher-throughput setting (paid)

Default to Standard. Go Advanced only when you need >4 KB values, >10k parameters, or parameter policies (e.g., “expire this param in 30 days”, “notify if not changed in 90 days”).

Hierarchical organization

Parameters are paths. Organize by environment / service / key:

text
/myapp/prod/database/url
/myapp/prod/database/password      (SecureString)
/myapp/prod/feature-flags/new-checkout
/myapp/staging/database/url

GetParametersByPath fetches a whole subtree in one call — load all of /myapp/prod/ at startup:

python
import boto3
ssm = boto3.client("ssm")

resp = ssm.get_parameters_by_path(
    Path="/myapp/prod/",
    Recursive=True,
    WithDecryption=True,   # decrypt SecureStrings
)
config = {p["Name"]: p["Value"] for p in resp["Parameters"]}
# paginate if > 10 params — use the paginator

IAM can be scoped to a path prefix — prod role can read /myapp/prod/*, staging role only /myapp/staging/*.

Parameter Store vs Secrets Manager

The decision matrix:

Parameter Store Secrets Manager
Cost free (Standard tier) ~$0.40 per secret / month + per-API-call
Automatic rotation no (you’d build it with EventBridge + Lambda) yes — built-in, RDS-native rotation, custom Lambda rotation
Max value size 4 KB (8 KB Advanced) 64 KB
Cross-region replication no (manual) yes (built-in)
Versioning yes (numeric versions) yes (version stages: AWSCURRENT/PENDING/PREVIOUS)
Resource policies (cross-account) no yes
Generates random secrets no yes (get_random_password)
Hierarchical paths yes no (flat names, slashes are just naming)
Plain (non-secret) config yes — this is its sweet spot overkill

Decision shortcut:

  • Plain config (URLs, flags, tuning params) → Parameter Store String. Always. Secrets Manager would be wasteful.
  • Secrets that don’t need rotation (third-party API keys you set once) → Parameter Store SecureString — free, encrypted, fine.
  • Secrets that need automatic rotation (DB passwords, especially RDS) → Secrets Manager — the built-in rotation is the whole value proposition.
  • Cross-account secret sharing, >4 KB secrets, version-staged rotation testing → Secrets Manager.

A common pattern: most config + static secrets in Parameter Store; only the rotation-critical credentials (RDS password) in Secrets Manager. You pay $0.40/mo per rotating secret instead of per every config value.

Note: Secrets Manager can reference Parameter Store and vice-versa in some integrations, but treat them as separate stores with the decision above.

Reading parameters in an app

python
import boto3
ssm = boto3.client("ssm")

# Single parameter
db_url = ssm.get_parameter(Name="/myapp/prod/database/url")["Parameter"]["Value"]

# Single SecureString — decrypt it
db_pw = ssm.get_parameter(
    Name="/myapp/prod/database/password", WithDecryption=True
)["Parameter"]["Value"]

# Many at once
resp = ssm.get_parameters(
    Names=["/myapp/prod/database/url", "/myapp/prod/database/password"],
    WithDecryption=True,
)

Don’t call get_parameter on every request. Like Secrets Manager, fetch once at startup / cold start and cache. For Lambda, the AWS Parameters and Secrets Lambda Extension provides a local cache + HTTP endpoint so you avoid hitting the SSM API on every invocation:

text
GET http://localhost:2773/systemsmanager/parameters/get?name=/myapp/prod/database/url

Versioning

Every update creates a new numeric version. You can read a specific version (Name:3) or use parameter labels for named versions. Useful for “roll back this config value” without keeping a separate history.

EnvVar injection in ECS / Lambda

Both ECS task definitions and Lambda can pull Parameter Store values at launch and inject them as environment variables — no SDK call in your code:

json
// ECS task definition
"secrets": [
  {"name": "DATABASE_URL", "valueFrom": "arn:aws:ssm:us-east-1:123:parameter/myapp/prod/database/url"},
  {"name": "DB_PASSWORD", "valueFrom": "arn:aws:ssm:us-east-1:123:parameter/myapp/prod/database/password"}
]

ECS resolves these at task start (the execution role needs ssm:GetParameters + kms:Decrypt). The container sees plain env vars. Same idea works with Secrets Manager ARNs.

Common gotchas

  • Calling get_parameter per request — API rate limits + latency. Cache at startup; use the Lambda extension.
  • Forgetting WithDecryption=TrueSecureString returns the ciphertext, not the value.
  • Missing kms:Decrypt — the role needs both ssm:GetParameter and kms:Decrypt on the encryption key.
  • Standard-tier throughput — shared account-wide throughput; a chatty app can throttle. Cache, or enable the Advanced higher-throughput setting.
  • Using Secrets Manager for plain config — wasteful at $0.40/secret/mo. Parameter Store String is free.
  • Using Parameter Store for rotating DB credentials — you’d have to build the rotation yourself; Secrets Manager does it natively. Use the right tool.
  • Path-based IAM mistakesarn:.../parameter/myapp/prod/* scopes correctly; forgetting the leading / in the parameter name breaks the ARN match.

Interview angle 5

  • “Parameter Store vs Secrets Manager — when each?” — Parameter Store for plain config (free) and static secrets (SecureString, free, encrypted). Secrets Manager when you need automatic rotation (especially RDS-native), cross-account sharing, >4 KB values, or version-staged rotation. Common pattern: config + static secrets in Parameter Store, only rotation-critical credentials in Secrets Manager.
  • “How do you give a service its config without baking it into the image?” — store under a path like /myapp/prod/*; either inject into env vars via the ECS task definition / Lambda config at launch, or fetch with get_parameters_by_path at startup. IAM scoped to the path prefix.
  • “SecureString — how does it work?” — value encrypted with KMS. WithDecryption=True on read returns the plaintext; the caller needs ssm:GetParameter and kms:Decrypt on the key.
  • “How do you avoid hitting the SSM API on every request?” — fetch + cache at startup/cold start; for Lambda use the AWS Parameters and Secrets Lambda Extension (local cache + localhost HTTP endpoint).
  • “Standard vs Advanced tier?” — Standard is free, 4 KB values, 10k params. Advanced is paid, 8 KB values, 100k params, plus parameter policies (expiration, change notifications). Default to Standard.

Contents 0