What Is AWS Secrets Manager? How It Works and When to Use It

AWS Secrets Manager is a managed service that stores sensitive credentials like database passwords, API keys, and OAuth tokens, then delivers them to your applications at runtime through a secure API. It keeps secrets out of your code, rotates them on a schedule, and controls who can access them through IAM.

The core decision is straightforward: use Secrets Manager for sensitive credentials that need rotation or strict lifecycle management. Use SSM Parameter Store for simpler configuration values and static secrets where rotation is not required. The rest of this page explains how Secrets Manager works, when each service fits, and how to use it correctly.

Simple explanation

Analogy

Imagine a hotel front desk safe. You hand over your valuables (the secret), get a receipt with a reference number (the secret name), and retrieve them later by showing your ID (IAM credentials). You never carry the valuables around the building, the safe is locked at all times, and the hotel logs every time someone opens it. Secrets Manager works the same way for your application credentials.

Think of Secrets Manager as a secure vault with an API. You put a secret in (a database password, an API key, an OAuth token), and your application retrieves it at runtime by asking for it by name. The secret is encrypted at rest, access is controlled by IAM, and every retrieval is logged.

A secret is any piece of information that would give an attacker access to a system if exposed. Database passwords, private keys, API tokens, and connection strings are all secrets.

Storing secrets in source code, Git repositories, container images, environment variable files committed to version control, or shared documents is dangerous. Anyone with access to the repo, the image, or the document has the credentials. Secrets Manager eliminates that risk by separating where the secret lives from where it is used. For more on why hardcoded credentials create real incidents, see why long-lived access keys are dangerous.

Why this matters

Leaked credentials are one of the most common causes of security breaches in cloud environments. The risks are concrete:

  • Hardcoded database passwords get committed to Git. Anyone who clones the repo has production access.
  • API keys in config files end up in container images, build logs, or error messages.
  • Manual password rotation causes outages when one application still uses the old password.
  • Shared credentials make it impossible to revoke access for one application without breaking others.
  • No audit trail means you cannot tell who accessed a credential or when.
Real example of the risk

A developer commits a database connection string to a public GitHub repo. Automated bots scrape GitHub for credentials within minutes. By the time the team notices, someone has already dumped the production database. Secrets Manager prevents this entirely: the password never exists in your codebase, so there is nothing to leak.

Secrets Manager addresses all of these problems. Credentials live in an encrypted store, applications fetch them at runtime, rotation happens automatically, each application gets its own credential, and every access is logged in CloudTrail.

How AWS Secrets Manager works

Here is the conceptual flow from storing a secret to an application using it:

  1. Store the secret. You create a secret in Secrets Manager with a name (e.g., prod/myapp/database) and a value (the JSON or string containing the credential).
  2. Encrypt with KMS. Secrets Manager encrypts the value using a KMS key. By default it uses the AWS-managed key aws/secretsmanager. You can specify a customer managed key for compliance or cross-account access.
  3. Control access with IAM. You attach an IAM policy to the application’s role granting secretsmanager:GetSecretValue on the specific secret ARN. You can also attach a resource-based policy to the secret itself.
  4. Application fetches at runtime. The application calls GetSecretValue via the AWS SDK. KMS decrypts the value server-side, and the plaintext secret is returned over TLS.
  5. Optionally rotate. Secrets Manager invokes a Lambda function on a schedule to generate a new credential, update the target service (e.g., change the RDS password), and store the new value.
  6. Application refreshes. On the next fetch, the application receives the new credential. Applications that cache secrets should use short TTLs and retry with a fresh fetch on authentication failure.
Mental model

Secrets Manager is not a config file replacement. It is an encrypted, access-controlled, audited credential store with a rotation engine attached. Your application never sees the secret until it explicitly asks for it, and every ask is logged.

What you can store in Secrets Manager

A secret in Secrets Manager is a name that maps to a JSON document or a plain string, up to 65 KB. Common types:

  • Database credentials including username, password, host, port, and database name (used with RDS, Aurora, Redshift, DocumentDB)
  • API keys for third-party services like payment providers, SaaS platforms, and messaging services
  • OAuth client secrets and tokens such as client IDs, client secrets, and refresh tokens for service integrations
  • TLS/SSL certificates and private keys for services that need to present or validate certificates
  • Application secrets like signing keys, encryption keys, webhook secrets, and SMTP credentials

Secrets are encrypted at rest using KMS. For details on how encryption keys work across AWS services, see encryption in AWS.

When to use Secrets Manager

Secrets Manager is the right choice when:

  • The credential needs automatic rotation, such as database passwords or API keys that expire
  • You are storing RDS, Aurora, Redshift, or DocumentDB credentials where built-in managed rotation is available
  • Third-party API keys that must be audited and access-controlled
  • Secrets consumed by Lambda, ECS, EKS, or EC2 applications at runtime
  • You need cross-account secret sharing with resource-based policies
  • Credentials used in CI/CD pipelines that should not be stored in pipeline config. See secrets in CI/CD pipelines
  • Compliance requires audit logging of every credential access
Scenario: A web app connecting to RDS

Your Django app runs on ECS and connects to a PostgreSQL database on RDS. Instead of putting the database password in an environment variable or config file, store it in Secrets Manager. The ECS task role has permission to fetch that one secret. When the password rotates every 30 days, the app picks up the new credential automatically. No redeployment needed.

When not to use Secrets Manager

Secrets Manager costs $0.40 per secret per month plus $0.05 per 10,000 API calls. It is not the right tool for everything:

  • Non-sensitive configuration values like endpoint URLs, feature flags, S3 bucket names, and region settings. Use SSM Parameter Store (free standard tier).
  • Feature flags and application config. AWS AppConfig or SSM Parameter Store are purpose-built for this.
  • Static settings that never change. If the value will not rotate and is not sensitive, Parameter Store is simpler and free.
  • High-volume lookups of non-secret data. The per-call pricing adds up quickly for data that does not need encryption or rotation.
Cost trap

Teams sometimes store every config value in Secrets Manager “just to be safe.” At 200 parameters, that is $80/month for data that does not need encryption or rotation. Put actual secrets in Secrets Manager and everything else in Parameter Store’s free tier.

Secrets Manager vs SSM Parameter Store

FeatureSecrets ManagerSSM Parameter Store
Best use caseCredentials that rotate (DB passwords, API keys)Config values, static secrets, feature flags
Automatic rotationYes, Lambda-based with managed support for RDS/Redshift/DocumentDBNo built-in rotation (manual or custom automation)
Pricing$0.40/secret/month + $0.05 per 10K API callsFree (Standard) or $0.05/parameter/month (Advanced)
Max value size65 KB4 KB (Standard) / 8 KB (Advanced)
VersioningStaging labels (AWSCURRENT, AWSPREVIOUS, AWSPENDING)Sequential version numbers
Cross-account accessResource-based policies on secretsShared via AWS RAM (Advanced tier only)
Access controlIAM policies + resource-based policies + KMS key policiesIAM policies (no resource-based policies on parameters)
EncryptionAlways encrypted with KMS (mandatory)Optional: SecureString uses KMS, String/StringList are plaintext
Operational complexityHigher: rotation Lambda, KMS key management, staging labelsLower: simple key-value store with optional encryption

Choose Secrets Manager when the credential rotates, needs cross-account sharing via resource policy, or requires the audit trail and lifecycle management that comes with a dedicated secrets service.

Choose Parameter Store when the value is non-sensitive config, a static secret that rarely changes, or when you want to avoid the per-secret monthly cost. Parameter Store’s free standard tier handles most configuration needs.

Analogy

Secrets Manager is like a bank safe deposit box. You pay a monthly fee, the bank changes the locks regularly, and there is a detailed access log every time you open it. Parameter Store is like a locked filing cabinet in your office: free to use, good enough for most documents, but nobody is changing the lock for you and there is no guard standing watch.

Creating and retrieving secrets

Create a secret via CLI

# Create a database credential secret
aws secretsmanager create-secret \
  --name "prod/myapp/database" \
  --description "Production RDS credentials for MyApp" \
  --secret-string '{"username":"myapp_user","password":"<generated-password>","host":"mydb.cluster-xxxx.us-east-1.rds.amazonaws.com","port":5432,"dbname":"myapp_prod"}'

Retrieve a secret via CLI

# Get the secret value as formatted JSON
aws secretsmanager get-secret-value \
  --secret-id "prod/myapp/database" \
  --query 'SecretString' --output text | python3 -m json.tool

Retrieve a secret in Python

import boto3
import json

def get_database_credentials():
    client = boto3.client("secretsmanager", region_name="us-east-1")

    response = client.get_secret_value(SecretId="prod/myapp/database")
    secret = json.loads(response["SecretString"])

    return {
        "host": secret["host"],
        "port": secret["port"],
        "database": secret["dbname"],
        "user": secret["username"],
        "password": secret["password"],
    }

Retrieve a secret in Node.js

const {
  SecretsManagerClient,
  GetSecretValueCommand,
} = require("@aws-sdk/client-secrets-manager");

const client = new SecretsManagerClient({ region: "us-east-1" });

async function getDatabaseCredentials() {
  const command = new GetSecretValueCommand({
    SecretId: "prod/myapp/database",
  });
  const response = await client.send(command);
  return JSON.parse(response.SecretString);
}

Each application that retrieves a secret needs an IAM role with permission scoped to the specific secret ARN. For background on how IAM policies work, see IAM policy structure.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/database-*"
    }
  ]
}
Watch for the ARN suffix

Secret ARNs end with a 6-character random suffix (e.g., -aB1cD2). Use a wildcard for the suffix (secret-name-*) in IAM policies. Using the base name without the suffix will not match, and the call will fail with AccessDenied. If you hit this, see fixing IAM AccessDenied errors.

Access control and encryption

Access to a secret is controlled at three layers:

  1. IAM identity policies. The application’s IAM role must have secretsmanager:GetSecretValue (and optionally secretsmanager:DescribeSecret) scoped to the specific secret ARN. Follow least privilege and never use "Resource": "*" for secret access.
  2. Resource-based policies. You can attach a policy directly to the secret to grant or deny access from specific principals, accounts, or VPC endpoints. This is how cross-account access works. You can use IAM policy conditions to restrict access further, for example limiting access to requests from a specific VPC endpoint.
  3. KMS key policies. The KMS key used to encrypt the secret must also allow the calling principal to perform kms:Decrypt. If you use the default AWS-managed key (aws/secretsmanager), this is handled automatically within the same account. For cross-account access or tighter control, use a customer managed key and grant decrypt permissions explicitly in the key policy.
Customer managed keys vs AWS managed key

The AWS-managed key is zero-effort. Secrets Manager uses it by default and you do not manage the key policy. A customer managed key (CMK) gives you full control over the key policy, lets you grant cross-account decrypt access, and supports key rotation on your own schedule. Use a CMK when compliance requires it or when you need cross-account secret sharing.

Rotation explained

Rotation is the process of periodically replacing a secret’s value with a new one: generating a new password, updating it in the target service, and storing the new value in Secrets Manager. This limits the window of exposure if a credential is compromised.

Analogy

Think of rotation like changing the locks on your house every month. Secrets Manager is the locksmith who shows up on schedule, swaps the lock, hands you the new key, and makes sure the old key still works for a few hours so nobody gets locked out mid-visit.

Managed rotation vs custom rotation

Managed rotation is available for supported AWS databases: Amazon RDS (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server), Aurora, Redshift, and DocumentDB. When you enable rotation for one of these, Secrets Manager provisions the Lambda function for you. You configure the schedule and the rotation strategy. You do not write the function.

Custom rotation is for everything else: third-party API keys, non-AWS databases, service accounts, and tokens. You write a Lambda function that implements the four-step rotation interface and tell Secrets Manager to invoke it on schedule.

The four-step rotation workflow

Every rotation Lambda, whether managed or custom, follows four steps:

  1. createSecret: Generate a new credential and store it in Secrets Manager as a new version with the staging label AWSPENDING.
  2. setSecret: Update the target service (e.g., change the database password) with the new credential.
  3. testSecret: Verify the new credential works by connecting to the target service using the AWSPENDING version.
  4. finishSecret: Move the staging label AWSCURRENT to the new version and AWSPREVIOUS to the old version.

If any step fails, the rotation stops and the AWSCURRENT version remains unchanged. The old credential keeps working. For a deeper walkthrough, see rotating secrets automatically in AWS.

What applications must do to survive rotation

Rotation changes the credential in the target service. Applications must be able to handle this:

  • Do not cache secrets indefinitely. Use a short cache TTL (the AWS Secrets Manager caching client defaults to 300 seconds). If your application reads the secret once at startup and never refreshes, it will fail after rotation.
  • Implement retry on authentication failure. When a connection fails with an authentication error, re-fetch the secret from Secrets Manager and retry. This handles the brief window during rotation when the old credential may already be replaced.
  • Use the AWS caching clients. AWS provides caching libraries for Python, Java, .NET, and Go that handle TTL-based caching and automatic refresh. Use them instead of building your own caching logic.
Anti-pattern: Read once, cache forever

An ECS service reads the database password at container startup and stores it in a variable for the lifetime of the process. Thirty days later, rotation changes the password. Every new database connection fails with “authentication failed.” The fix: use a caching client with a TTL, or re-fetch the secret on any authentication error.

Common mistakes

  1. Caching secrets permanently in memory. Applications that read a secret once at startup and never refresh will break after rotation. Use a caching client with a TTL of a few minutes and implement retry logic that re-fetches on authentication failure.
  2. Using broad IAM policies for secret access. "Resource": "*" on secretsmanager:GetSecretValue gives every secret in the account to that role. Always scope to the specific secret ARN with the random suffix wildcard.
  3. Skipping the rotation test. Enabling rotation without running an immediate test leaves a broken setup that will fail silently at the next scheduled rotation, often at the worst possible time.
  4. Storing non-secret config in Secrets Manager. Feature flags, endpoint URLs, and bucket names do not need encryption or rotation. Putting them in Secrets Manager wastes $0.40/month per value and adds unnecessary complexity. Use SSM Parameter Store.
  5. Sharing one secret across multiple applications. If you rotate the credential, every application sharing it must handle the change simultaneously. Give each application its own database user and its own secret for independent rotation and revocation.
  6. Forgetting the KMS key policy for cross-account access. The IAM policy and resource-based policy on the secret are not enough. The KMS key that encrypts the secret must also grant kms:Decrypt to the cross-account principal, or the call fails with an access error.

Frequently asked questions

What is the difference between Secrets Manager and Parameter Store?

Secrets Manager is built for credentials that need automatic rotation and lifecycle management: database passwords, API keys, OAuth tokens. It includes built-in rotation via Lambda and costs $0.40 per secret per month. SSM Parameter Store is for configuration values and static secrets where you do not need rotation. The standard tier is free. Choose Secrets Manager when the credential rotates or must be audited tightly. Choose Parameter Store when the value is simple config or a secret that rarely changes.

Does Secrets Manager always use Lambda for rotation?

For managed rotation of supported AWS databases (RDS, Redshift, DocumentDB), Secrets Manager provisions and manages the rotation Lambda function for you. You do not write it. For custom secrets like third-party API keys or non-AWS databases, you write your own Lambda function that implements the four-step rotation workflow. In both cases Lambda is the execution mechanism, but the amount of work you do varies.

How does an application read a secret securely?

The application calls GetSecretValue through an AWS SDK (Python, Node.js, Java, Go, etc.) using an IAM role that has secretsmanager:GetSecretValue permission scoped to the specific secret ARN. The secret is decrypted server-side by KMS and returned over TLS. No credentials are stored in the application code, container image, or config file.

Can Secrets Manager share secrets across accounts or regions?

Yes. For cross-account access, attach a resource-based policy to the secret granting the remote account or role access, and ensure the KMS key policy also allows the remote principal to decrypt. For cross-region, use Secrets Manager replica secrets to replicate a secret to other regions. This is useful for multi-region applications and disaster recovery.

When should I avoid using Secrets Manager?

Avoid Secrets Manager for non-sensitive configuration values (feature flags, endpoint URLs, bucket names), static settings that never rotate, and high-volume lookups where the API cost matters. SSM Parameter Store (free standard tier) or AWS AppConfig is usually a better fit for those cases.

Last verified: 30 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.