What Parameter Store is for
Parameter Store is a key-value store for configuration: database hostnames, feature flags, API endpoints and small secrets. It keeps values out of code and AMIs, gives you versioning, and controls access with IAM.
| Type | Use for | Encrypted |
|---|---|---|
String | Plain config (db.example.internal) | No |
StringList | Comma-separated list (a,b,c) | No |
SecureString | Passwords, tokens | Yes, with KMS |
Standard tier is free for up to 10,000 parameters and 4 KB values; advanced tier allows bigger values and parameter policies (expiry) at a cost. Check the current limits and pricing page before relying on numbers.
Step 1: Name parameters by path
Use a hierarchy so you can grant access and fetch by prefix:
/app1/prod/db/host
/app1/prod/db/password
/app1/prod/feature/new-checkout
/app1/dev/db/host
Step 2: Create parameters
aws ssm put-parameter --name /app1/prod/db/host \
--type String --value "app1-prod.cluster-xyz.ap-south-1.rds.amazonaws.com"
aws ssm put-parameter --name /app1/prod/db/password \
--type SecureString --value 'S3cure-Value' \
--key-id alias/app1-prod
aws ssm put-parameter --name /app1/prod/feature/new-checkout \
--type String --value "false" \
--tags Key=app,Value=app1 Key=env,Value=prod
Leaving out --key-id uses the AWS managed key alias/aws/ssm. A customer managed key lets you control who can decrypt via the key policy, and is required for cross-account reads.
Update an existing value with --overwrite; each update creates a new version:
aws ssm put-parameter --name /app1/prod/feature/new-checkout --value "true" --overwrite
aws ssm get-parameter-history --name /app1/prod/feature/new-checkout \
--query 'Parameters[].[Version,Value,LastModifiedDate]' --output table
Tip
Avoid putting secret values on the command line on shared hosts; they end up in shell history. Use
--value file://secret.txtand delete the file, or create SecureStrings from your IaC tool with the value from a secure pipeline variable.
Step 3: Read parameters
# One value
aws ssm get-parameter --name /app1/prod/db/host --query Parameter.Value --output text
# A SecureString, decrypted
aws ssm get-parameter --name /app1/prod/db/password --with-decryption \
--query Parameter.Value --output text
# Everything under a path
aws ssm get-parameters-by-path --path /app1/prod --recursive --with-decryption \
--query 'Parameters[].[Name,Value]' --output table
# A specific version
aws ssm get-parameter --name /app1/prod/feature/new-checkout:3
From Python (Lambda or EC2)
import boto3
ssm = boto3.client("ssm")
def load_config(prefix="/app1/prod"):
cfg, token = {}, None
while True:
kwargs = {"Path": prefix, "Recursive": True, "WithDecryption": True}
if token:
kwargs["NextToken"] = token
resp = ssm.get_parameters_by_path(**kwargs)
for p in resp["Parameters"]:
cfg[p["Name"].removeprefix(prefix + "/")] = p["Value"]
token = resp.get("NextToken")
if not token:
return cfg
CONFIG = load_config() # load once per container, not per request
Loading once outside the handler avoids hitting the API on every invocation. For Lambda, the AWS Parameters and Secrets Lambda Extension adds a local cache if you need refreshes without redeploying.
From an ECS task definition
"secrets": [
{ "name": "DB_PASSWORD", "valueFrom": "arn:aws:ssm:ap-south-1:111122223333:parameter/app1/prod/db/password" }
]
The task execution role needs ssm:GetParameters on that ARN and kms:Decrypt on the key.
Step 4: IAM access by path
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ssm:GetParameter", "ssm:GetParameters", "ssm:GetParametersByPath"],
"Resource": "arn:aws:ssm:ap-south-1:111122223333:parameter/app1/prod/*"
},
{
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:ap-south-1:111122223333:key/<key-id>"
}
]
}
Note the ARN has no slash between parameter and the path, because the path already starts with /.
Common errors
| Error | Cause | Fix |
|---|---|---|
ParameterNotFound | Wrong name, wrong region, or a version that doesn't exist | Check --region and exact path (case-sensitive) |
AccessDeniedException on GetParameter | IAM resource ARN doesn't match the path | Fix ARN pattern |
AccessDeniedException ... kms:Decrypt | Role can read the parameter but not decrypt | Allow kms:Decrypt in IAM and key policy |
ThrottlingException | Many callers polling at startup | Cache values; raise throughput setting; use GetParametersByPath |
Parameter Store or Secrets Manager?
| Need | Use |
|---|---|
| Plain config, flags, endpoints | Parameter Store |
| Small secrets, no rotation required | Parameter Store SecureString |
| Automatic rotation (RDS, Redshift, custom Lambda) | Secrets Manager |
| Cross-region secret replication | Secrets Manager |
Prevent problems later
- Agree on a path convention (
/<app>/<env>/<component>/<key>) before teams invent their own. - Manage parameters in Terraform/CloudFormation, but keep secret values out of state files where you can.
- Alert on
PutParameterandDeleteParameterfor/*/prod/*paths through CloudTrail and EventBridge. - Use a customer managed KMS key per environment so you can revoke decrypt access cleanly.