---
title: AWS Secrets Manager vs Parameter Store: When to Use Which
description: Secrets Manager rotates and costs $0.40 per secret per month. Parameter Store doesn't rotate and is mostly free. Pricing, rotation, encryption, cross-account access, and the decision criteria for picking each — including the hybrid pattern most production accounts end up at.
url: https://www.factualminds.com/blog/aws-secrets-manager-vs-parameter-store-when-to-use-which/
datePublished: 2026-02-18T00:00:00.000Z
dateModified: 2026-05-14T00:00:00.000Z
author: Palaniappan P
category: Security & Compliance
tags: secrets-manager, parameter-store, aws, security, devops
---

# AWS Secrets Manager vs Parameter Store: When to Use Which

> Secrets Manager rotates and costs $0.40 per secret per month. Parameter Store doesn't rotate and is mostly free. Pricing, rotation, encryption, cross-account access, and the decision criteria for picking each — including the hybrid pattern most production accounts end up at.

Every application has secrets — database credentials, API keys, encryption keys, OAuth tokens — and configuration values — feature flags, endpoint URLs, timeout settings, environment-specific parameters. AWS provides two services for managing these: Secrets Manager and SSM Parameter Store. Both store key-value pairs securely, both integrate with IAM for access control, and both can be referenced from Lambda, ECS, EC2, and [CloudFormation](/blog/aws-cloudformation-best-practices-infrastructure-as-code/).

**May 2026 refresh:** Secrets Manager rotation pricing still dominates comparisons—re-verify **per-secret monthly charges + API call tiers** against Parameter Store Advanced Parameter tiers whenever AWS adjusts billing dimensions.

The overlap creates confusion. This guide provides clear decision criteria based on the features that actually differ.

## Feature Comparison

| Feature                        | Secrets Manager                          | Parameter Store (Standard)             | Parameter Store (Advanced)      |
| ------------------------------ | ---------------------------------------- | -------------------------------------- | ------------------------------- |
| **Cost**                       | $0.40/secret/month + $0.05/10K API calls | Free (up to 10,000 params)             | $0.05/advanced param/month      |
| **Max size**                   | 64 KB                                    | 4 KB                                   | 8 KB                            |
| **Automatic rotation**         | Built-in (Lambda-based)                  | No                                     | No                              |
| **Cross-account access**       | Native (resource policies)               | No                                     | No                              |
| **Cross-Region replication**   | Built-in                                 | No                                     | No                              |
| **Encryption**                 | KMS (mandatory)                          | KMS (optional for SecureString)        | KMS (optional for SecureString) |
| **Versioning**                 | Automatic (staging labels)               | Automatic (version history)            | Automatic                       |
| **Parameter policies**         | N/A                                      | N/A                                    | TTL, expiration notifications   |
| **Hierarchy**                  | Flat (name only)                         | Hierarchical paths (/app/prod/db_host) | Hierarchical paths              |
| **Max parameters/secrets**     | 500,000                                  | 10,000 (standard), 100,000 (advanced)  | 100,000                         |
| **CloudFormation integration** | Dynamic reference                        | Dynamic reference                      | Dynamic reference               |
| **ECS integration**            | Native (task definition)                 | Native (task definition)               | Native                          |
| **Lambda integration**         | Lambda extension (cached)                | Lambda extension (cached)              | Lambda extension                |

## When to Use Secrets Manager

### Automatic Secret Rotation

Secrets Manager's killer feature is built-in rotation. A Lambda function automatically rotates secrets on a schedule — no manual intervention, no downtime:

```
Schedule (every 30 days)
  → Secrets Manager triggers rotation Lambda
  → Lambda creates new credentials in the database
  → Lambda stores new credentials in Secrets Manager
  → Lambda verifies new credentials work
  → Applications automatically get new credentials on next retrieval
```

**Supported rotations out of the box:**

- RDS (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server)
- Aurora
- Redshift
- DocumentDB
- Custom rotation (any secret via custom Lambda function)

For database credentials, Secrets Manager with rotation is the standard. Manually rotating database passwords is error-prone and creates security risk during the transition period. Rotation eliminates both problems.

### Cross-Account Access

Secrets Manager supports resource-based policies that grant access to other AWS accounts:

```json
{
  "Effect": "Allow",
  "Principal": { "AWS": "arn:aws:iam::222233334444:root" },
  "Action": ["secretsmanager:GetSecretValue"],
  "Resource": "*"
}
```

In a [multi-account organization](/blog/aws-multi-account-strategy-landing-zone-best-practices/), this enables a central secrets account to share credentials with workload accounts without duplicating secrets.

Parameter Store does not support cross-account access natively. You must use IAM role assumption or replicate parameters across accounts.

### Cross-Region Replication

Secrets Manager replicates secrets to multiple Regions for [disaster recovery](/blog/aws-disaster-recovery-strategies-pilot-light-warm-standby-multi-site/):

```
Primary Region (us-east-1) → Replica (us-west-2) → Replica (eu-west-1)
```

Applications in the DR Region access the local replica — same secret, same ARN pattern, no cross-Region API calls during failover.

### Use Secrets Manager For

- Database credentials (with rotation)
- Third-party API keys that require periodic rotation
- OAuth client secrets
- Encryption keys managed outside KMS
- Secrets shared across AWS accounts
- Secrets replicated across Regions for DR

## When to Use Parameter Store

### Hierarchical Configuration

Parameter Store organizes parameters in a hierarchical path structure:

```
/myapp/production/database/host       = prod-db.cluster-abc.us-east-1.rds.amazonaws.com
/myapp/production/database/port       = 5432
/myapp/production/database/name       = myapp_prod
/myapp/production/feature-flags/dark-mode  = true
/myapp/production/feature-flags/new-ui     = false
/myapp/staging/database/host          = staging-db.cluster-def.us-east-1.rds.amazonaws.com
/myapp/staging/database/port          = 5432
```

**Retrieve all parameters for an environment:**

```
GetParametersByPath: /myapp/production/
→ Returns all production parameters in one API call
```

This hierarchical model maps naturally to application configuration — environment, service, and setting levels. Secrets Manager uses flat names without hierarchy.

### Free Tier (Standard Parameters)

Standard parameters in Parameter Store are free — no per-parameter charge, no API call charges (within standard throughput). For applications with dozens or hundreds of configuration values, this saves significant cost compared to Secrets Manager ($0.40/secret/month).

| Scenario                   | Secrets Manager Cost | Parameter Store Cost |
| -------------------------- | -------------------- | -------------------- |
| 10 secrets                 | $4/month             | Free                 |
| 50 configuration values    | $20/month            | Free                 |
| 100 mixed secrets + config | $40/month            | Free (standard)      |
| 500 values                 | $200/month           | Free (standard)      |

### Three Parameter Types

| Type         | Encryption    | Use Case                                             |
| ------------ | ------------- | ---------------------------------------------------- |
| String       | None          | Non-sensitive config (URLs, feature flags, timeouts) |
| StringList   | None          | Comma-separated lists (allowed IPs, region list)     |
| SecureString | KMS encrypted | Sensitive config (passwords, API keys)               |

SecureString parameters are encrypted at rest with KMS and decrypted only when retrieved by authorized IAM principals. They provide the same encryption security as Secrets Manager — the difference is no built-in rotation.

### Use Parameter Store For

- Application configuration (URLs, ports, timeouts, feature flags)
- Environment-specific settings
- Non-rotating secrets (API keys that change rarely)
- Large numbers of parameters (cost-sensitive)
- Hierarchical configuration that maps to app structure

## Using Both Together

The best practice for most applications is to use both services for their strengths:

```
Secrets Manager:
  - Database credentials (with rotation)
  - Third-party API keys (with rotation)
  - OAuth secrets

Parameter Store:
  - Application configuration
  - Feature flags
  - Environment-specific URLs and settings
  - Non-sensitive parameters
```

**CloudFormation example using both:**

```yaml
Resources:
  MyFunction:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          # Configuration from Parameter Store
          DB_HOST: '{{resolve:ssm:/myapp/prod/database/host}}'
          DB_PORT: '{{resolve:ssm:/myapp/prod/database/port}}'
          # Secrets from Secrets Manager
          DB_PASSWORD: '{{resolve:secretsmanager:myapp/prod/db-password:SecretString:password}}'
```

## Integration Patterns

### Lambda

Both services provide Lambda extensions that cache values locally, reducing API calls and latency:

```
Lambda invocation → Check local cache → Cache hit → Return value (0ms)
                                      → Cache miss → API call → Cache value → Return (50-100ms)
```

**Lambda extension cache TTL:** 300 seconds by default. Adjust based on how frequently your configuration changes.

**Environment variables vs runtime retrieval:**

- **Environment variables** — Set at deployment time. Simple but requires redeployment to change values.
- **Runtime retrieval** — Read from Parameter Store or Secrets Manager during execution. Changes take effect without redeployment (after cache TTL expires).

**Recommendation:** Use environment variables for values that change only with deployments (database host, table names). Use runtime retrieval for values that change independently (feature flags, rate limits).

### ECS/Fargate

ECS natively injects secrets and parameters into container environment variables:

```json
{
  "containerDefinitions": [
    {
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789:secret:prod/db-password"
        },
        {
          "name": "API_KEY",
          "valueFrom": "arn:aws:ssm:us-east-1:123456789:parameter/myapp/prod/api-key"
        }
      ]
    }
  ]
}
```

ECS retrieves the values at container startup and injects them as environment variables. The container never sees the Secrets Manager or Parameter Store API — the integration is transparent.

### EC2

Use the SSM Agent (pre-installed on Amazon Linux) to retrieve parameters at boot:

```bash
DB_HOST=$(aws ssm get-parameter --name /myapp/prod/database/host --query Parameter.Value --output text)
DB_PASS=$(aws secretsmanager get-secret-value --secret-id myapp/prod/db-password --query SecretString --output text | jq -r .password)
```

For EC2 instances, prefer IAM instance profiles for authentication — never hardcode credentials in user data scripts.

## Security Best Practices

### Encryption

- Secrets Manager: All secrets are encrypted with KMS (mandatory). Use a customer-managed key for audit trail and independent access control.
- Parameter Store: Use `SecureString` type for any sensitive value. Specify a customer-managed KMS key for production secrets.

### Access Control

Apply least-privilege IAM policies:

```json
{
  "Effect": "Allow",
  "Action": ["ssm:GetParameter", "ssm:GetParametersByPath"],
  "Resource": "arn:aws:ssm:*:*:parameter/myapp/production/*"
}
```

This grants access to production parameters only — not staging, development, or other applications. Scope access by path prefix, not by wildcard.

### Audit Logging

Both services log API calls to [CloudTrail](/services/aws-cloud-security/). Monitor for:

- Unauthorized access attempts (failed GetSecretValue or GetParameter calls)
- Unusual access patterns (new IAM principals accessing secrets)
- Bulk parameter retrieval (potential data exfiltration)

Set [CloudWatch alarms](/blog/aws-cloudwatch-observability-metrics-logs-alarms-best-practices/) for failed secret access attempts.

### Rotation Policy

| Secret Type            | Rotation Frequency     | Method                             |
| ---------------------- | ---------------------- | ---------------------------------- |
| Database credentials   | 30-90 days             | Secrets Manager automatic rotation |
| API keys (internal)    | 90 days                | Secrets Manager custom rotation    |
| API keys (third-party) | Per provider policy    | Manual or custom rotation          |
| OAuth client secrets   | 90-180 days            | Custom rotation                    |
| Encryption keys        | Annual (KMS automatic) | KMS key rotation                   |

## Common Mistakes

### Mistake 1: Secrets in Environment Variables

Storing secrets directly in [CloudFormation](/blog/aws-cloudformation-best-practices-infrastructure-as-code/) template parameters, ECS task definition environment variables, or Lambda environment variables as plaintext. These values are visible in the console, CLI, and API responses. Always reference Secrets Manager or Parameter Store SecureString — never embed plaintext secrets.

### Mistake 2: Using Secrets Manager for All Configuration

Storing 200 application configuration values in Secrets Manager at $0.40/secret/month costs $80/month. Parameter Store standard is free. Use Secrets Manager for secrets that need rotation or cross-account access. Use Parameter Store for everything else.

### Mistake 3: No Rotation

Credentials that never rotate are ticking time bombs. A compromised credential remains valid indefinitely. Enable rotation on all database credentials and rotate API keys on a schedule.

### Mistake 4: Overly Broad Access

Granting `secretsmanager:GetSecretValue` on `*` gives access to every secret in the account. Scope access to specific secret ARNs or name prefixes. Use Parameter Store path-based policies for hierarchical access control.

## Getting Started

Secrets and configuration management is a foundational security practice. Secrets Manager provides the rotation and cross-account capabilities that production secrets require. Parameter Store provides the hierarchical organization and cost-effectiveness that application configuration needs. Use both for their strengths.

For secrets management architecture, [security hardening](/services/aws-cloud-security/), and [DevOps pipeline integration](/services/devops-pipeline-setup/), talk to our team.

[Contact us to secure your application secrets →](/contact-us/)

## FAQ

### Should I use AWS Secrets Manager or SSM Parameter Store?
Secrets Manager for anything that needs automatic rotation (RDS, Redshift, Aurora, DocumentDB credentials, third-party API keys with rotation hooks), cross-account sharing via resource policies, or cross-region replication. Parameter Store SecureString for static secrets, configuration values, and high-volume parameters where the per-secret cost would add up. Plain Parameter Store String for non-sensitive config.

### How does Secrets Manager rotation work?
A Lambda function triggered on a schedule (default 30 days) creates a new credential in the database, stores it as the AWSPENDING version, verifies the new credential works, then promotes it to AWSCURRENT. Applications retrieving the secret automatically receive the new value on next fetch. Out-of-the-box rotation supports RDS engines, Aurora, Redshift, and DocumentDB; custom rotation Lambdas handle anything else.

### Can SSM Parameter Store store secrets safely?
Yes — use the SecureString parameter type with KMS encryption (preferably a customer-managed CMK). Access is gated by IAM `ssm:GetParameter` plus `kms:Decrypt` on the key. Parameter Store does not rotate, does not support cross-account natively (use replication or assume-role), and caps each parameter at 4 KB (Standard) or 8 KB (Advanced) — but for most static secrets it is dramatically cheaper than Secrets Manager.

### How much do Secrets Manager and Parameter Store cost?
Secrets Manager: $0.40 per secret per month plus $0.05 per 10,000 API calls. Parameter Store Standard: free up to 10,000 parameters with no API charges. Parameter Store Advanced: $0.05 per parameter per month plus $0.05 per 10,000 API calls. At scale, the cost difference is meaningful — 5,000 application configs in Secrets Manager would cost $2,000/month vs free in Parameter Store Standard.

### How do I share secrets across AWS accounts?
Secrets Manager supports resource-based policies that grant `secretsmanager:GetSecretValue` to other accounts directly, plus the KMS key policy must permit those principals. Parameter Store has no native cross-account sharing — workarounds are IAM role assumption (the consuming account assumes a role in the secrets account), parameter replication via Lambda, or moving the secret to Secrets Manager.

---

*Source: https://www.factualminds.com/blog/aws-secrets-manager-vs-parameter-store-when-to-use-which/*
