What Is AWS Secrets Manager? Passwords Out of Your Code
AWS Secrets Manager is a service where you store passwords, API keys, and other credentials so they never sit in your source code — and here is the part that surprises most people: the default encryption key (aws/secretsmanager) costs you nothing to use, and rotation can run as often as every four hours without a separate rotation fee. When your application needs a credential, it makes an API call at runtime, Secrets Manager decrypts the value using a key from AWS KMS (Key Management Service — the AWS service that manages encryption keys), and delivers it over TLS (Transport Layer Security — the protocol that secures data in transit). The credential itself never exists in your code repository, your container image, your environment variables file, or your build logs in plaintext form. That single shift — from a hardcoded string to a runtime lookup — is what removes the password from every place it has leaked over the years.
The rest of this page walks through every part of the service in the order a beginner actually hits it: what a "secret" is, what is inside one, what it costs and when the bill gets ugly, how rotation works, how it compares to the four services people always stack it against, and the exact steps for the six things you will do on day one. No prior AWS security experience assumed — every term gets explained at first use as we use asusual in our site. If you are new to our site, feel free to check our AWS guide we covered from starting for our non tech readers as well.
If you already know what a secrets manager is and just need the commands, jump straight to creating your first secret or the four retrieval commands. If you are deciding between services, the Parameter Store comparison table and the pricing traps section are the two that will save you the most time.
What AWS Secrets Manager Actually Is (In Plain Terms)
Start with the problem it solves, because the service makes no sense without it. Somewhere in your code — in a config file, an environment variable, a database connection string — there is probably a password. That password has a lifecycle you did not design: it got committed to git, it now sits in your repository history forever, it is visible to anyone who can read the Lambda function configuration in your AWS account, and it is the same password it was six months ago because changing it means updating every place it lives.
Secrets Manager replaces that pattern with one move: the password moves into a managed vault inside AWS, and your code makes an API call to fetch it when the application starts or when a connection is needed. The word "secret" here means any credential or sensitive value — a database username and password, an API key for a third-party service, an OAuth token (OAuth is the open standard for authorization — how one service gets permission to act on another on a user's behalf), a private TLS certificate, or any blob of text you would not want a stranger to read.
AWS manages, retrieves, and rotates database credentials, application credentials, OAuth tokens, API keys, and other secrets throughout their lifecycles. Over thirty AWS services can consume a secret directly — RDS (Relational Database Service, AWS's managed database offering), Aurora, Redshift (AWS's data warehouse), DocumentDB, ECS (Elastic Container Service), EKS (Elastic Kubernetes Service), Lambda, CodeBuild, Glue, EMR, SageMaker, and more. Instead of pasting a password into each service's configuration, you point the service at the secret's ARN (Amazon Resource Name — the unique identifier AWS assigns to every resource, like a postal address for a thing in the cloud).
♂️ Jake's Reality Check
"So I've been storing my database password in a .env file on the server and in an environment variable in my Lambda. Everyone does it that way. Why is that suddenly a crisis?"
Because the .env file and the environment variable both outlive the code review that approved them. Jake's .env file sits in his home directory on an EC2 instance (Elastic Compute Cloud — AWS's virtual servers) that three people have SSH access to. His Lambda's environment variable is readable by anyone in the account with lambda:GetFunction permissions, and it appears in every CloudTrail log (AWS's audit trail for API calls) of every UpdateFunctionConfiguration call that ever set it. One person with read access reads the database password for every customer record. That is the gap this service closes: the credential becomes an ARN pointing to an encrypted blob, and reading the blob requires an explicit IAM permission you can scope to one role, one network, or one account.
"Here is the mental model I give people," Ethan says, when Jake asks him to make sense of it. "You know how a hotel works. You check in at the front desk, they verify who you are, and they hand you a key card that opens exactly one room. The card is not the room key — it is a temporary credential that the hotel issued after checking your identity, and the hotel can deactivate it at any time. Secrets Manager is the front desk. Your application walks up with its IAM role — that is the ID card — and asks for a specific room's key. If the role does not have permission for that room, the answer is no. And if the hotel rotates the key cards every night, a card someone copied yesterday is worthless today. That is rotation."
"The part people underestimate," Ethan continues, "is what it removes from your life. You stop writing scripts to change database passwords. You stop coordinating downtime between the app team and the database team because the new password has to be deployed everywhere at once. You stop finding credentials in a public git repository three years after someone left the company. The service handles the update; your application fetches the current value; the two never need to know each other's schedule."
One thing this service is not: a configuration store. If you are storing the endpoint URL for your inventory service, a feature flag, or an AMI ID (Amazon Machine Image — the template for an EC2 instance's boot volume), that belongs in Parameter Store, a different AWS service. AWS's own documentation draws the line: for secrets such as database credentials, API keys, or tokens, they recommend Secrets Manager because it is purpose-built with automatic rotation and cross-region replication. For static configuration, Parameter Store is the intended home, and its standard tier is free.
AWS also tells you what does NOT belong here, and the list matters because putting the wrong thing in the wrong service either costs you money or leaves a gap:
- AWS credentials (access keys — the long-lived ID and secret pairs used to sign AWS API requests) → IAM (Identity and Access Management, the service that controls who can do what in your AWS account) handles these.
- Encryption keys (the keys that encrypt data) → AWS KMS. Secrets Manager uses KMS to encrypt what it stores; it does not replace KMS.
- SSH keys (the key pairs used to log into servers) → Amazon EC2 Instance Connect is AWS's recommendation.
- Private keys and certificates (TLS certificates for websites) → AWS Certificate Manager.
How AWS Secrets Manager Works: The Three Moving Parts
Three mechanisms make up the service, and understanding them explains every behavior you will encounter later. Ethan walks Jake through them here, because the concepts are the ones that trip people up on day one.
Part 1: Encryption (AWS KMS)
Every secret is encrypted at rest — meaning while it sits in storage — using an encryption key you own and store in AWS KMS. "At rest" versus "in transit" is the distinction: at rest means stored on disk; in transit means moving over a network. Secrets Manager handles both: encrypted at rest with your KMS key, delivered over TLS when you ask for it.
"Wait," Jake says. "So my password is encrypted, but the key that encrypts it also lives in AWS? Is that not just moving the problem?"
"It is the exact question to ask," Ethan tells him. "But the key and the data have different security models. The KMS key never leaves the KMS service — you cannot export it. Decryption happens inside KMS, and KMS logs every decryption request to CloudTrail with the identity of who asked. So if someone wants your password, they need two things: permission to call GetSecretValue on that secret, and permission to use that KMS key. Two doors, both logged, both controlled by you separately. Compare that to your .env file, where the password is sitting there in plaintext and the only door is your operating system's file permissions."
The default is the AWS managed key aws/secretsmanager — AWS creates it in your account automatically, manages its policy, and rotates it on AWS's schedule. Using it costs nothing. If you need to access the secret from another AWS account, or if you want to rotate the encryption key yourself or apply a custom key policy (the policy that controls who can use the KMS key), you choose a customer managed key instead — a key you create in KMS and control fully.
With a customer managed key, you can restrict decryption to requests that originate only from Secrets Manager in a specific region, using the kms:ViaService condition key set to secretsmanager.<region>.amazonaws.com. You can go further and scope the key to a specific secret using encryption context conditions — a set of key-value pairs KMS attaches to the encryption so the key can only decrypt data encrypted with the same context. This is the depth available when you need it; the default path costs nothing and requires none of this.
Part 2: Access Control (IAM and Resource Policies)
"Who can read my secret?" is the question IAM answers. IAM is AWS's permission system: every request to any AWS service carries the identity of the requester (an IAM user, an IAM role, or an assumed role session), and IAM checks that identity against the policies attached to it.
Secrets Manager uses two layers of policy. Identity-based policies are attached to the IAM user or role and say what that identity can do — "this Lambda execution role can call GetSecretValue on secret X." Resource-based policies are attached to the secret itself and say who can interact with it — "only the role with this ARN can read this secret, regardless of what their identity policy says." When both exist, both must allow the action.
For the network side, you can attach a VPC endpoint condition to a policy so a secret can only be read from inside a specific VPC (Virtual Private Cloud — your private, isolated section of the AWS network). The request never leaves the Amazon network. This is what AWS means when the best practices page says "run your infrastructure on private networks": create a Secrets Manager VPC endpoint, attach a condition requiring requests to come through it, and the secret is unreachable from the public internet entirely.
Part 3: Versioning (Staging Labels)
This is the part that catches people off guard, so Ethan gives it the slow explanation.
"When you change a secret's value — either you update it or the rotation process changes it — Secrets Manager does not keep a history of every value the secret has ever had," Ethan tells Jake. "What it does is track three specific versions at any moment, using labels it calls staging labels. AWSCURRENT is the one your application gets when it asks for the secret. AWSPREVIOUS is the one before that — the rollback target. AWSPENDING exists only during rotation, when the new credential is being created and tested before it goes live."
"So I cannot ask for what the password was last Tuesday?" Jake asks.
"Not unless you gave that version a custom label while it was current. The system guarantees exactly three labeled versions exist at any time. You can attach up to 20 labels total across the versions, and one version can carry multiple labels, but two versions cannot share the same label — there is only one AWSCURRENT at a time. Labeled versions are never removed. Unlabeled versions are considered deprecated, and the service cleans up deprecated versions when there are more than 100 of them — but never removes versions created less than 24 hours ago."
"That sounds fragile," Jake says. "What if I need to see every password change for an audit?"
"CloudTrail logs every API call — who called PutSecretValue, when, from where. What CloudTrail does not log is the secret value itself, because it is marked sensitive. So the audit trail says 'a new version was created at 14:03 by this role' without recording what the password actually was. If you need the values themselves, you would have to capture them yourself at write time. But in practice, what auditors want is who changed what and when, and that you have."
What this means in practice
- Rollback is a label move, not a restore: you call
update-secret-version-stageto shift AWSCURRENT to an older version. The version itself was always there — only the pointer moves. - When you move AWSCURRENT, the service automatically moves AWSPREVIOUS to the version AWSCURRENT just left. The two labels swap.
- The maximum size of a secret value is 65,536 bytes. Secret names run 1-512 characters, alphanumeric plus
/_+=.@-.
Creating Your First Secret: Console and CLI, Step by Step
Two ways in. The console is better the first time because it walks you through the JSON structure for database credentials; the CLI (Command Line Interface — the tool you run in a terminal to call AWS services) is what your scripts will use.
Console Method: The Full Walkthrough
- Open the Secrets Manager console at
https://console.aws.amazon.com/secretsmanager/— the console is the web interface for AWS, and this URL takes you directly to the Secrets Manager section. - Choose Store a new secret — the orange button near the top right.
- On the Choose secret type page, you pick one of three paths, and this choice determines what the console asks you next:
- Database credentials — you choose the database type (MySQL, PostgreSQL, etc.), then pick the actual database instance from a list of ones AWS can see in your account, then enter the username and password. The console builds the JSON structure for you, including the connection details.
- Other type of secret — the choice for API keys, access tokens, and anything that is not a database credential. You enter your secret as JSON key/value pairs (JSON is JavaScript Object Notation — a text format for structured data, written as
"key": "value"pairs inside curly braces), or you switch to the Plaintext tab and enter it in any format at all — a raw API key, a certificate block, whatever. - Partner secret — for managed external secrets from companies that have built direct integration with Secrets Manager: Salesforce, Snowflake, Datadog, MongoDB Atlas, GitLab, and others on the partner list.
- For Encryption key, choose
aws/secretsmanager— the default. There is no cost for this key. Switch to a customer managed key only if you need cross-account access or want to control the key policy yourself. - Choose Next.
- On the Configure secret page, enter a Secret name and Description. The name is what every CLI call, IAM policy, and application config will reference — pick something like
prod/myapp/databaserather thansecret1, because six months from now "secret1" tells you nothing. Add tags if you want cost tracking or tag-based access control. You can also set resource permissions (which roles can access this secret) and multi-region replication here or later. - Choose Next.
- On the Configure rotation page, you can turn on automatic rotation now — set the schedule and pick the rotation strategy — or skip it and come back. Rotation setup for database secrets asks for the credentials of a user with permission to change passwords on the database. Choose Next.
- On the Review page, check everything, then choose Store. You are done.
CLI Method: Two Patterns
For a simple key-value secret — say an API key for a third-party service:
aws secretsmanager create-secret \
--name MyTestSecret \
--description "My test secret created with the CLI." \
--secret-string '{"user":"diegor","password":"EXAMPLE-PASSWORD"}'
The backslashes at the end of each line are line continuations in bash — they let you write one long command across multiple lines. The --secret-string value is the JSON that will be stored, encrypted, as the secret's value.
For a database credential that rotation will later manage, use the JSON structure Secrets Manager's rotation templates expect — this exact set of keys is what the rotation Lambda function looks for:
aws secretsmanager create-secret \
--name MyTestSecret \
--secret-string file://mycreds.json
The file:// prefix tells the CLI to read the value from a local file instead of the command line. Contents of mycreds.json:
{
"engine": "mysql",
"username": "saanvis",
"password": "EXAMPLE-PASSWORD",
"host": "my-database-endpoint.us-west-2.rds.amazonaws.com",
"dbname": "myDatabase",
"port": "3306"
}
⚠️ What this actually breaks
When you type a secret into a command shell, the command lands in your shell history — the ~/.bash_history file on Linux that records everything you typed. Anyone who reads that file reads your password. AWS's best practices page calls this out directly and recommends mitigating the risk before using the CLI to enter sensitive information: load the value from a file (as in the second example), use the console instead, or clear your shell history immediately after. The --secret-string '{"password":"..."}' pattern in the first example is safe for documentation but not for a production credential.
Retrieving Secrets: The Four Commands You Actually Use
Four API calls cover almost everything you will do after creation. Each has a specific job, and confusing them is the most common beginner mistake — people call describe-secret and wonder where the password is, or call get-secret-value when they wanted inventory.
| Command | What it returns | Charged as an API call? | Use it for |
|---|---|---|---|
get-secret-value |
The decrypted secret string or binary — the actual password | Yes | Your application at runtime — the call your code makes |
describe-secret |
Metadata only: description, KMS key, tags, rotation settings, version list — no secret value | Yes | Checking rotation status, seeing which version is current, auditing |
list-secrets |
All secrets in the account (excluding ones marked for deletion), with metadata | Yes | Inventory — finding what exists, filtering by name or tag |
batch-get-secret-value |
Multiple decrypted secret values in one call | Yes | Fetching a group of related secrets without looping |
"Notice that all four count toward your API bill," Ethan points out when Jake asks about the charges. "It is not just the one that returns the password. Describing a secret, listing your secrets, batch-fetching — each is a call, each is $0.05 per 10,000. It sounds trivial until you have a script that runs describe-secret every thirty seconds and generates 86,400 calls a month."
The One Command Your Application Uses
aws secretsmanager get-secret-value --secret-id MyTestSecret
The --secret-id can be the secret's name or its ARN. The response includes the ARN, name, version ID, the secret string itself, and the staging labels on that version. If the secret was created through the console with key/value pairs, the secret string comes back as JSON — your code parses it and extracts the field it needs.
One privacy behavior worth knowing: the secret value does not appear in CloudTrail log entries. CloudTrail logs that the GetSecretValue call happened — who called it, when, for which secret — but not what it returned. The value is marked sensitive, and the service strips it from the audit log.
To list every secret in the account:
aws secretsmanager list-secrets
The output includes name, ARN, description, tags, and rotation status for each. list-secrets supports filters — name (prefix match, case-sensitive), description (prefix, not case-sensitive), tag-key, tag-value, primary-region, owning-service, and all (breaks the value into words and searches every attribute, not case-sensitive). You can apply up to 10 filters.
One consistency caveat: all Secrets Manager operations are eventually consistent, meaning a change you just made might not appear in list results for up to five minutes. If you create a secret and immediately run list-secrets, it might not be there yet. For the most recent state of a specific secret, call describe-secret on it directly — that reads the authoritative record.
To check a specific secret's metadata without exposing the value:
aws secretsmanager describe-secret --secret-id MyTestSecret
This is the diagnostic call you will use most: it tells you the rotation schedule, which KMS key encrypts the secret, when it was last accessed, and which versions exist with which staging labels — without ever showing the credential itself.
Secret Rotation: How It Actually Runs (And Why It Is Safe)
Rotation is the feature that justifies the service's existence, and it is also the part with the most moving pieces. You can rotate secrets on a schedule or on demand using the console, the AWS SDKs (Software Development Kits — the libraries for calling AWS from your programming language), or the CLI — and the schedule can be as aggressive as every four hours.
AWS's own best practices page puts the reason bluntly: "If you don't change your secrets for a long period of time, the secrets become more likely to be compromised." Rotation turns every credential into a short-lived one, which shrinks the window in which any leaked copy of it is useful.
Rotation Strategies: Single User vs. Alternating Users
Two strategies, and the choice matters for whether your application experiences downtime during a rotation.
Single user rotation changes the password on the same database user every time. One user account, new password. It is simpler to set up, but there is a window during rotation where the old password has been changed on the database and not every client has picked up the new one — connections established with the old credential can fail when the database rejects them.
Alternating users rotation switches between two database users — say, myapp_user1 and myapp_user2. When it is time to rotate, the strategy updates the password on the user that is NOT currently active, then switches the secret to point at that user. Your application's existing connections keep working because the user they authenticated as still exists with its old, unchanged password. This is the zero-downtime option, and it is the one AWS's tutorials walk through in detail.
"Think of it like changing a lock on a building with two doors," Ethan tells Jake. "Single-user rotation locks one door, changes the lock, unlocks it. While the lock is being changed, nobody can use that door. Alternating-users rotation changes the lock on door B while everyone is still walking through door A. When the new lock on B works, you switch the sign to point at B. Nobody ever waits. The catch is you need two doors — two database users — and both need the same permissions."
Rotation Mechanisms: Lambda vs. Managed
How the rotation actually executes depends on the secret type. For many types of secrets — including databases hosted on Amazon RDS, Amazon DocumentDB, and Amazon Redshift clusters — Secrets Manager uses an AWS Lambda function (AWS's serverless compute — you write a function, AWS runs it when triggered, you pay per invocation) to update the secret and the database or service simultaneously.
For secrets managed by other AWS services, you use managed rotation, which does not require a Lambda function at all. And for secrets held by Secrets Manager's integration partners — third-party SaaS (Software as a Service) companies like Salesforce, Snowflake, Datadog, GitLab, Jenkins, MongoDB Atlas, and others — there is managed external secrets rotation, which updates the secret on the partner's system without a Lambda function and without you writing rotation code.
The Lambda-based path is where the AWSPENDING staging label earns its keep. When rotation triggers, the Lambda function creates a new version of the secret with the AWSPENDING label, changes the credential on the actual database or service, tests that the new credential works by connecting with it, and only then moves AWSCURRENT to the new version and shifts AWSPREVIOUS to the old one. If the Lambda fails partway through — the database is unreachable, the new password does not meet the database's complexity policy — the AWSPENDING version just sits there and the old credential keeps working. Your application never notices, because AWSCURRENT never moved.
One security restriction on rotation functions: Secrets Manager only allows a Lambda rotation function to rotate the secret directly — the rotation function cannot call another Lambda function to do the rotating. That is an anti-delegation rule, and it exists to prevent a compromised rotation function from pivoting into arbitrary code execution paths through a chain of function calls.
✅ Why this is the one to use
For RDS, DocumentDB, and Redshift credentials: native rotation with alternating users. The templates exist, the fail-safe behavior is built in, and the alternative — rotating passwords by hand on a calendar reminder — is exactly the habit this service exists to kill. For third-party SaaS secrets: check the partner list first; if your provider is on it, managed external rotation means you never write a line of rotation code. For everything else: the Lambda templates on the AWS Samples GitHub repository cover most databases and can be modified for custom cases.
When Rotation Fails: The Symptoms and Causes
When rotation fails, the symptom is almost always the same: describe-secret shows a version stuck with the AWSPENDING label, the RotationEnabled flag is still true, but the LastRotatedDate is old. The causes, in order of how often they show up:
- Network — the Lambda rotation function cannot reach the database. The fix AWS recommends: create a Secrets Manager VPC endpoint in the same VPC so requests from the Lambda rotation function to Secrets Manager do not leave the Amazon network, and make sure the Lambda's security group (the virtual firewall rules attached to the function) allows outbound traffic to the database's port.
- Permissions — the Lambda execution role (the IAM role the function runs as) lacks
secretsmanager:GetSecretValue,secretsmanager:PutSecretValue, orsecretsmanager:UpdateSecretVersionStage, or lacks the KMS decrypt permission on the secret's encryption key. - Credential mismatch — the secret's stored username does not exist on the database, or the stored password for the superuser that performs rotation is itself wrong.
- Rotation window — the schedule's window is shorter than the Lambda's timeout, so the function gets killed partway.
Secrets Manager logs rotation events to CloudTrail, and CloudWatch Events (AWS's event routing service) can push a notification when a rotation succeeds or fails. That alert is the difference between finding out on Tuesday and finding out three months later — and the setup is a few clicks in the console.
Updating, Rolling Back, and Understanding Versions
Every time you update a secret's value or the secret rotates, Secrets Manager creates a new version. The versioning model — three labels, no linear history — was covered in the architecture section. Here are the practical operations.
To update a secret's value and create a new AWSCURRENT version:
aws secretsmanager update-secret \
--secret-id MyTestSecret \
--secret-string '{"user":"diegor","password":"NEW-PASSWORD"}'
This creates a new version with the AWSCURRENT label, and the old version automatically gets AWSPREVIOUS. If automatic rotation is set up and you manually update the value, Secrets Manager considers that a valid rotation when it calculates the next rotation date — the service does not fight you; a manual change resets the rotation clock.
To roll back to the previous version — the operation people look for most and find least intuitive — you do not "restore" anything; you move the AWSCURRENT label:
aws secretsmanager update-secret-version-stage \
--secret-id MyTestSecret \
--version-stage AWSCURRENT \
--move-to-version-id a1b2c3d4-5678-90ab-cdef-EXAMPLE22222 \
--remove-from-version-id a1b2c3d4-5678-90ab-cdef-EXAMPLE11111
The version ID is a UUID (Universally Unique Identifier — a 36-character string that identifies this specific version) you get from describe-secret or list-secret-version-ids. Whenever you move AWSCURRENT, the service automatically moves the AWSPREVIOUS label to the version AWSCURRENT was removed from — the two labels swap. If this action results in the last label being removed from a version, that version becomes deprecated and can be cleaned up.
You cannot roll back to "the version from three rotations ago" unless you gave that version a custom label while it was current. The system only guarantees AWSCURRENT, AWSPREVIOUS, and AWSPENDING exist at any moment.
Deleting Secrets and the Recovery Window
Deleting a secret is a two-step process with a built-in safety net. When you call delete-secret, the secret is not immediately destroyed — it enters a scheduled deletion state with a recovery window, 30 days by default, configurable from 7 to 30 days. During the window, you are not billed for the secret, but it still appears in list-secrets results with a DeletedDate and ScheduledDeletionDate, and it still reserves the name — you cannot create a new secret with the same name until the old one is fully gone.
To delete a secret with the default 30-day recovery window:
aws secretsmanager delete-secret --secret-id MyTestSecret
To shorten the window to 7 days (the minimum):
aws secretsmanager delete-secret --secret-id MyTestSecret --recovery-window-in-days 7
To restore a secret during the recovery window — undo the deletion before it becomes permanent:
aws secretsmanager restore-secret --secret-id MyTestSecret
"The mistake I see is people being afraid to delete because they think it is immediate and irreversible," Ethan says. "It is neither. You have a month to change your mind, and the restore is one command with no data loss. The cost angle matters too: you stop paying for the secret the moment it enters the deletion state, not when the window expires. So if you are cleaning up a hundred dead credentials from an old project, the bill drops immediately."
If you need the secret gone immediately with no recovery window, that option exists, but it is irreversible — AWS's documentation describes it as a permanent deletion that cannot be undone. For most cases, the default 30-day window is the right choice: it protects against the typo where you delete the wrong ARN, and the billing stops regardless.
Cross-Region Replication: Secrets in Multiple Regions
For disaster recovery and multi-region applications, Secrets Manager can replicate your secrets to other AWS regions automatically. You specify the regions where a secret needs to be replicated, and the service creates regional read replicas — copies that stay synchronized with the primary secret. When the primary secret's value changes (whether you update it or rotation changes it), the new value propagates to all replica regions.
Each replica is billed as a separate secret at the same $0.40 per month. A secret replicated to three additional regions costs $1.60 per month in storage. The replicas are read-only from the application's perspective — they exist so that a regional application can fetch its credentials from a nearby region without cross-region latency, and so that a regional outage does not make secrets unreachable.
When you replicate a secret, you choose between using a multi-region KMS key (a KMS key that exists in multiple regions and can encrypt/decrypt across them) or an independent KMS key in each replica region. The choice depends on your compliance requirements: a multi-region key is simpler to manage; independent keys give you regional isolation where a compromise of one region's key does not affect another.
If the primary region has a serious problem, you can promote a replica to a standalone secret — it stops being a replica and becomes its own primary, independent of the original. That is the disaster recovery move: your application in the surviving region promotes the local replica and keeps running.
AWS Secrets Manager Pricing: The Real Numbers and the Traps
Two line items, no tiers, no seats, no permanent free tier. Starting July 15, 2025, new AWS customers receive up to $200 in AWS Free Tier credits applicable toward eligible services including Secrets Manager — the free plan runs 6 months after account creation, and credits expire 12 months from the account creation date. After that, or for existing accounts, it is pure usage-based:
- $0.40 per secret per month — a replica secret (a copy in another region) is considered a distinct secret and also billed at $0.40 per replica per month. Secrets stored for less than a full month are prorated based on hours.
- $0.05 per 10,000 API calls — every GetSecretValue, DescribeSecret, ListSecrets, CreateSecret, and so on.
Rotation does not have a separate line-item fee. You pay the normal stored-secret charge and any API calls the rotation workflow generates. Creating new secret versions is not billed separately.
AWS's own pricing page gives three examples, and the second one is the warning label:
| Scenario | Secrets | API calls/month | Monthly cost |
|---|---|---|---|
| Production web app | 15 | 4,040 | $6.02 |
| Ephemeral auth tokens | 5,000,000 | 10,000,000 | $2,850.00 |
| Organization with $40K+ AWS spend | 1,500 | 900,000 | $612.50 |
The second example is the trap. Five million one-hour tokens at 2 API calls each: $2,800 in secret storage (every token counts as a secret, prorated at $0.00056 per hour of existence) plus $50 in API calls. The service is priced for long-lived credentials — things that live for months — not for short-lived session tokens. If you are generating tokens by the million, that workload belongs in a different design entirely: IAM roles with STS (Security Token Service — AWS's service for issuing temporary credentials), or a purpose-built token service, not a secrets store.
For the more normal cases, the math is manageable. The production web app example — 15 secrets, 4,040 API calls, weekly rotation — lands at $6.02 per month. A 1,500-secret organization at 20 retrievals per secret per day lands at $612.50 per month. The cost driver to watch is API calls from high-frequency retrieval: a Lambda that fetches the secret on every invocation, with no caching, at 100 requests per second, generates roughly 260 million API calls per month — about $1,300 in API charges alone.
♂️ Jake's Reality Check
"I've got maybe ten secrets — three database passwords, a couple of API keys, an OAuth token. Is this thing going to cost me $50 a month for something I could do with a locked file?"
Ten secrets at $0.40 is $4 per month in storage. The API calls are where you either stay at pennies or balloon — it depends entirely on whether you cache. Jake's ten secrets, retrieved once per Lambda cold start with the caching library, run a few cents in API charges. Jake's ten secrets, fetched on every single request with no cache, on a site doing any real traffic, run hundreds of dollars. The difference is one design decision, not the service's price.
How to Actually Cut the Bill
AWS's best practices page is explicit about the highest-leverage moves, and they are not about switching services:
- Use client-side caching. Secrets Manager provides caching libraries for Java, Python, .NET, Go, and Rust, plus the AWS Parameters and Secrets Lambda Extension. The cache holds decrypted values in your application's memory for a configurable time-to-live, so your code makes one API call instead of thousands. This is the single biggest cost lever, and it also cuts latency because memory access is faster than an API call.
- Group fields into one JSON secret. Instead of five secrets for host, port, username, password, and dbname, make one secret with all five as JSON keys. Five secrets at $0.40 becomes one secret at $0.40, and five GetSecretValue calls per connection setup becomes one.
- Move non-secret config to Parameter Store. The endpoint URL of your inventory service is not a secret. The standard tier of Parameter Store is free, and AWS's own comparison table draws exactly this line: Parameter Store for static configuration, Secrets Manager for credentials and encrypted data requiring rotation.
- Delete secrets you are not using. You stop being billed the moment the secret enters the deletion state — not when the recovery window expires. The recovery window is a safety net, not a billing period.
AWS Secrets Manager vs. Parameter Store: The Decision Table
This is the comparison that matters most because both services are in your account already, both use KMS for encryption, and the wrong answer costs you either money or security. AWS publishes the distinction in their own documentation: "If you manage credentials such as usernames, passwords, or any other secrets, we recommend using AWS Secrets Manager. Secrets Manager is purpose-built for managing secrets such as database credentials, API keys, and supported third-party software-vended secrets."
"Can I just use Parameter Store with SecureString for my database password and skip the $0.40?" Jake asks, because it is the question everyone asks.
"You can, and for a hobby project it is a reasonable choice," Ethan says. "But look at what you give up. Parameter Store has no rotation — you change the password on the database yourself, and you update the parameter yourself, and those two things have to happen in an order that does not break your application at 2 AM. There is no cross-region replication, so if us-east-1 has a bad day, your secrets are unreachable from your DR (disaster recovery) region. There are no resource-based policies, so you cannot attach a policy to the parameter itself that says 'only this role can read this.' And CloudTrail does not log parameter retrieval the way it logs secret retrieval. For a production database credential, those are not nice-to-haves; they are the lifecycle management you are paying for."
| Feature | Parameter Store | Secrets Manager |
|---|---|---|
| Use case | Static configuration — values that do not contain credentials | Credentials and sensitive data requiring rotation, replication, or fine-grained access control |
| Typical data | AMI IDs, environment names, endpoint URLs, feature flags, tuning parameters | Database credentials, API keys, OAuth tokens, private keys, third-party secrets |
| Encryption | Optional — only SecureString type parameters are encrypted, using AWS KMS |
Always on — every secret encrypted at rest with AWS managed or customer managed KMS key |
| Credential rotation | None — you change the value manually | Automatic, as often as every 4 hours, with native database and partner integrations |
| Cross-region replication | Not built in | Yes — regional read replicas, kept in sync with the primary |
| Resource-based policies | No | Yes — attach a policy to the secret itself controlling who can access it |
| Cost | Standard tier free; advanced tier and higher throughput billed | $0.40 per secret per month + $0.05 per 10,000 API calls |
| Standard tier limits | 10,000 standard parameters per account/Region; 100,000 advanced parameters | Secrets are counted individually at $0.40 each |
The way to use both together, which AWS supports directly: put your secrets in Secrets Manager, and reference them from Parameter Store parameters when your tooling expects a parameter path. Systems Manager's documentation describes this as "referencing AWS Secrets Manager secrets from Parameter Store parameters" — your application calls ssm:GetParameter with a path like /awsreference/secretsmanager/MyTestSecret, and Parameter Store fetches from Secrets Manager behind the scenes. The secret is still stored, encrypted, and rotated in Secrets Manager; Parameter Store acts as the retrieval proxy for tools that only speak parameter paths.
AWS Secrets Manager vs. KMS: They Are Not Competitors
The confusion is common: both services encrypt things, both use keys, and the names sound adjacent. But they operate at different layers, and AWS's documentation is unambiguous about the division. Secrets Manager uses KMS keys to encrypt secrets; it does not replace KMS. For encryption keys themselves, AWS recommends KMS.
KMS is the key management service. It creates, stores, and controls access to encryption keys, and it performs cryptographic operations — encrypt, decrypt, sign, verify — with those keys. The keys themselves never leave the KMS service; you cannot export them. Secrets Manager is a consumer of KMS: every secret is encrypted with a KMS key (the AWS managed aws/secretsmanager key by default, or a customer managed key you choose), and when you retrieve a secret, Secrets Manager calls KMS to decrypt it before sending it to you over TLS.
"Think of it as two different jobs," Ethan tells Jake. "KMS is the locksmith — it makes keys, stores keys, and turns keys in locks when you ask. Secrets Manager is the safe deposit box room — it stores your valuables, checks your ID before handing them over, and uses the locksmith's keys to lock and unlock the boxes. You do not choose between them; you use both, and the default setup where Secrets Manager uses the aws/secretsmanager key requires zero configuration on your part."
The questions they answer are different:
- "Where do I store my database password and rotate it every 30 days?" → Secrets Manager.
- "Where does the key that encrypts my S3 bucket live?" → KMS.
- "How do I encrypt a field in my application's own database?" → KMS, via the AWS Encryption SDK.
For a deeper treatment of KMS itself — the key hierarchy, envelope encryption (the pattern of encrypting data with a data key that is itself encrypted with a master key), key policies versus IAM policies, and the aws/secretsmanager managed key — the AWS KMS guide covers that service end to end.
vs. HashiCorp Vault and Azure Key Vault
Two comparisons come up constantly, and both have honest answers that are not "AWS is best."
vs. HashiCorp Vault
Vault is a self-managed (or HCP-managed — HashiCorp Cloud Platform, their hosted offering) secrets platform that runs on your infrastructure or theirs. The trade is control versus operational burden. Vault gives you: dynamic secrets generated on demand per client, a wider range of secrets engines (PKI for certificates, transit for encryption-as-a-service, database for credential brokering, cloud credentials for AWS/GCP/Azure), a single tool across AWS, GCP, Azure, and on-premises, and no per-secret storage fee. What it costs you: you run the Vault server, you handle its high availability, you back up or replicate its storage backend, you patch it, and you staff the knowledge to operate it safely. A Vault cluster is a production system you own.
"The honest framing," Ethan says, "is this: if your infrastructure is entirely or mostly on AWS, Secrets Manager's zero operational overhead and native IAM integration are difficult to beat. You are not running a secrets service; you are calling one. If you are multi-cloud, or you need dynamic per-request credentials rather than rotated long-lived credentials, or you have compliance requirements that say you must control the entire secrets chain — Vault is the tool built for that problem. It is more work, and the work buys you capabilities AWS's service does not aim to provide."
vs. Azure Key Vault
Azure Key Vault is Microsoft's answer, and it bundles three functions that AWS splits across services: secrets (what Secrets Manager does), keys (what KMS does), and certificates (what ACM and ACM PCA do). If your workloads are in Azure, Key Vault is the default answer the same way Secrets Manager is in AWS — it integrates with Azure's identity system (Entra ID, formerly Azure AD) the way Secrets Manager integrates with IAM.
For a mixed environment, the pattern that works is one secrets service per cloud, with a policy layer on top — not trying to stretch one cloud's service across the other. AWS Secrets Manager does not integrate with Azure, and Azure Key Vault does not integrate with AWS; the boundary is each cloud's identity system, and fighting that is more expensive than running both.
Best Practices That Actually Change Outcomes
AWS's own best practices page lists ten, and the order is roughly the order of impact. The ones that change outcomes most, with the reasoning behind them:
Choose the encryption key deliberately
AWS's recommendation: for most cases, use the aws/secretsmanager AWS managed key, because there is no cost for using it. Switch to a customer managed key only when you need cross-account access or want to apply your own key policy. When you do make that switch, AWS tells you exactly what to put in the policy: assign secretsmanager.<region>.amazonaws.com to the kms:ViaService condition key, which limits the key to requests that come from Secrets Manager — no other service can use it even if their policy tries. Then use encryption context conditions to scope the key to specific secrets.
Use caching — this is the one that saves the most money
The best practices page is blunt: "To use your secrets most efficiently, we recommend you use one of the following supported Secrets Manager caching components to cache your secrets and update them only when required." The libraries exist for Java, Python, .NET, Go, and Rust; the AWS Parameters and Secrets Lambda Extension covers Lambda specifically; the AWS Workload Credentials Provider standardizes consumption across Lambda, ECS, EKS, and EC2. Without caching, every request your application serves can trigger a GetSecretValue call; with it, the value sits in memory for a TTL you set, and the service sees a fraction of the traffic. The cost and latency difference is one to two orders of magnitude.
Limit access with least privilege and VPC conditions
"Least privilege" means the IAM policy attached to your application's role grants exactly the permissions on exactly the resources it needs — nothing broader. For Secrets Manager, that looks like secretsmanager:GetSecretValue on one specific secret ARN, not secretsmanager:GetSecretValue on *. Beyond IAM, the patterns AWS recommends:
- Block broad access in resource policies — in identity policies that allow
PutResourcePolicy, setBlockPublicPolicy: trueso users can only attach resource policies that do not allow broad access. Secrets Manager uses Zelkova (AWS's automated reasoning engine for policy analysis) to analyze resource policies for broad access and reject them. - Limit requests with VPC endpoint conditions — attach a condition to the policy requiring requests to come through a specific VPC endpoint, so the secret is readable only from inside your network. An attacker with stolen credentials from outside your VPC gets denied at the network layer.
- Use tag-based access control (ABAC) — tag secrets by environment (
env=prod) and application (app=payments), then write policies that match on tags rather than enumerating ARNs. New secrets with the right tags inherit the right access automatically.
Find the secrets you already leaked
CodeGuru Reviewer (AWS's automated code review service) integrates with Secrets Manager to use a secrets detector that finds unprotected secrets in your code — hardcoded passwords, database connection strings, user names, and more. Amazon Q (AWS's AI assistant for developers) can scan your codebase for security vulnerabilities and code quality issues. Before you migrate credentials into Secrets Manager, scan for the ones you forgot you committed in 2019 — the migration is the moment to clean the history, not just the current code.
Run on private networks
Create a Secrets Manager VPC endpoint (a PrivateLink endpoint — a private connection between your VPC and the AWS service that does not traverse the public internet) so requests from your VPC to Secrets Manager stay inside the Amazon network. If you enable private DNS for the endpoint, you can keep using the default DNS name for the Region, like secretsmanager.us-east-1.amazonaws.com, and your applications need no code changes. Then add a condition to your permission policies requiring requests to come through the VPC endpoint — the secret is now unreachable from anywhere outside your network.
When Things Break: Failure Modes and What They Mean
The failure modes are few, which is a strength, but each has a specific meaning the error message does not spell out. Here are the ones you will actually hit, in the order you will hit them:
- AccessDeniedException on GetSecretValue — three possible causes, and the order to check them: first, the IAM policy does not grant
secretsmanager:GetSecretValueon the secret's ARN; second, the caller lackskms:Decrypton the secret's KMS key (this is the one people forget, because the IAM policy on the secret looks correct and the KMS permission is separate); third, the secret's resource policy explicitly denies the caller. Check the KMS permission second — the error looks identical for all three causes, but the KMS one is the silent killer because the IAM side looks fine. - ResourceNotFoundException on a secret that ListSecrets shows — the API is eventually consistent; a just-created or just-deleted secret may not be visible for up to five minutes. Call DescribeSecret directly for the authoritative state of that specific secret.
- ResourceExistsException on CreateSecret — a secret with that name already exists, including one sitting in the deletion recovery window. Secrets in the recovery window still reserve the name, so you cannot recreate until the window expires or you force-delete.
- InvalidParameterException — almost always the secret name: names run 1-512 characters, alphanumeric plus
/_+=.@-only, and the secret value cannot exceed 65,536 bytes. - Rotation stuck in AWSPENDING — the Lambda rotation function failed partway. The old credential still works because AWSCURRENT never moved, so your application is fine — this is a background failure you notice via monitoring, not an outage. Check CloudTrail for the Lambda's errors, then check the Lambda's network path to the database and its execution role's permissions.
For auditing after an incident: CloudTrail logs every Secrets Manager API call — who, when, which secret, which action. GetSecretValue's secret value is not included in the log entries; the call is logged, the value is not. For ongoing monitoring, CloudWatch (AWS's monitoring and alerting service) can alert when a secret remains unused for a period — useful for finding dead credentials to delete. CloudWatch Events can push notifications when Secrets Manager rotates a secret or when rotation fails. GuardDuty (AWS's threat detection service) can detect threats involving secrets.
"The one thing I tell people about monitoring this service," Ethan says, "is that the failure you care about is the silent one. A secret that cannot be read throws an error your application sees immediately — loud, obvious, fixed by a permission change. A rotation that has been failing for three months is silent: the old password keeps working, nothing breaks, and the whole point of rotation — shrinking the window a leaked credential is useful — quietly stops happening. Set the CloudWatch alert on rotation failure. It is two minutes of setup, and it is the difference between rotation being a security control and rotation being a checkbox."
Frequently Asked Questions
What is AWS Secrets Manager in simple terms?
It is a service where you store passwords, API keys, and other credentials instead of putting them in your code. Your application asks the service for the credential at runtime, the service hands it over encrypted-in-transit, and the service can change the credential on the actual database or API automatically on a schedule. The credential never lives in your source code, your container, or your environment variables in plaintext.
How does AWS Secrets Manager work technically?
Three components: encryption, access control, and versioning. Secrets are encrypted at rest with a KMS key (the default aws/secretsmanager key at no cost, or a customer managed key you control). Access is governed by IAM identity policies, resource policies on the secret, and optionally VPC endpoint conditions. Versioning uses staging labels — AWSCURRENT, AWSPREVIOUS, AWSPENDING — rather than a full history; labeled versions persist, unlabeled ones are cleaned up when there are more than 100. Rotation runs through a Lambda function (for databases and custom cases) or managed rotation (for partner services), creating the new version as AWSPENDING, updating the actual credential, then promoting it to AWSCURRENT only after it works.
How much does AWS Secrets Manager cost?
$0.40 per secret per month, plus $0.05 per 10,000 API calls. Replica secrets in other regions count as separate secrets at the same rate. Secrets stored for less than a month are prorated by hours. New AWS accounts (since July 15, 2025) get up to $200 in Free Tier credits applicable to the service for 6 months on the free plan. Rotation itself has no separate fee — you pay the stored-secret charge plus the API calls the rotation workflow generates, and creating new secret versions is not billed separately.
Is AWS Secrets Manager free?
Not permanently. New AWS customers since July 15, 2025 get up to $200 in Free Tier credits usable toward Secrets Manager — the free plan runs 6 months after account creation, and the credits expire 12 months from account creation. After that, the per-secret and per-API-call charges apply with no ongoing free allocation. If you need a permanently free option for non-secret configuration, Parameter Store's standard tier is free.
What is the difference between AWS Secrets Manager and Parameter Store?
Parameter Store is for static configuration — AMI IDs, endpoint URLs, feature flags — and its standard tier is free. Secrets Manager is for credentials and sensitive data, with automatic rotation (as often as every 4 hours), cross-region replication, staging-label versioning, resource-based policies, and per-secret audit logging. AWS's own documentation recommends Secrets Manager specifically for "credentials such as usernames, passwords, or any other secrets" and Parameter Store for "static configuration, key-value storage without deployment or validation." You can reference a Secrets Manager secret from a Parameter Store parameter when your tooling expects a parameter path.
How do I create a secret in AWS Secrets Manager?
Console: open console.aws.amazon.com/secretsmanager, choose Store a new secret, pick the type (database credentials, other type for API keys, or partner secret), choose the encryption key (the default aws/secretsmanager key costs nothing), give it a name and description, and store it. CLI: aws secretsmanager create-secret --name MyTestSecret --secret-string '{"user":"...","password":"..."}' for a simple case, or point --secret-string at a JSON file with the engine, username, password, host, dbname, and port keys if rotation will manage it.
How do I list all secrets in AWS Secrets Manager?
Run aws secretsmanager list-secrets. It returns all secrets in the account, excluding those marked for deletion (add --include-planned-deletion to include those). You can filter by name (prefix, case-sensitive), description (prefix, not case-sensitive), tag-key, tag-value, primary-region, owning-service, or all (searches all attributes, not case-sensitive), with up to 10 filters. The operation is paginated, and results are eventually consistent — for the most recent state of a specific secret, call describe-secret instead.
How do I get a secret value from AWS Secrets Manager?
aws secretsmanager get-secret-value --secret-id MyTestSecret. The secret-id can be the name or the ARN. By default this returns the AWSCURRENT version; pass --version-stage AWSPREVIOUS to get the previous one, or --version-id with a specific UUID. The response includes the secret string (or binary), the version ID, and the staging labels. If the secret was created through the console, the secret string is a JSON structure you parse client-side.
How do I describe a secret in AWS Secrets Manager?
aws secretsmanager describe-secret --secret-id MyTestSecret. This returns the metadata — description, KMS key ARN, tags, rotation configuration, version list with staging labels, created and last-accessed dates — but not the encrypted secret value. It is the call you use to check whether rotation is enabled and when it last ran, or to get the version ID you need for a rollback.
How do I update a secret value in AWS Secrets Manager?
aws secretsmanager update-secret --secret-id MyTestSecret --secret-string '{"user":"...","password":"NEW-VALUE"}'. This creates a new version with the AWSCURRENT label; the old version automatically gets AWSPREVIOUS. If automatic rotation is set up and you manually update the value, Secrets Manager considers that a valid rotation when it calculates the next rotation date — it does not fight you.
How do I delete a secret in AWS Secrets Manager?
aws secretsmanager delete-secret --secret-id MyTestSecret. This enters the secret into a scheduled deletion state with a 30-day recovery window by default (minimum 7 days via --recovery-window-in-days). During the window you are not billed, but the secret still reserves its name and can be restored with aws secretsmanager restore-secret --secret-id MyTestSecret. After the window expires, the deletion is permanent. You stop being billed the moment the secret enters the deletion state, not when the window expires.
How often can AWS Secrets Manager rotate secrets?
As often as every four hours, per AWS's best practices documentation. You set the schedule using a cron expression (the scheduling syntax that specifies times like "every day at 2 AM" or "every 4 hours") or an interval in the rotation configuration. Rotation does not carry a separate fee — you pay the normal per-secret storage charge and the API calls the rotation workflow generates.
What is the difference between Secrets Manager and KMS?
They are not competitors — Secrets Manager uses KMS. KMS manages encryption keys: it creates them, stores them, controls access to them, and performs encrypt/decrypt operations. Secrets Manager stores credentials and other secrets, encrypting each one with a KMS key (the AWS managed aws/secretsmanager key by default, at no cost, or a customer managed key you choose). If you are asking "where do I store a database password," the answer is Secrets Manager; if you are asking "where does the key that encrypts my data live," the answer is KMS.
What is versioning in AWS Secrets Manager?
Every change to a secret's value creates a new version. Secrets Manager does not keep a full linear history — it tracks three specific versions using staging labels: AWSCURRENT (what your application gets by default), AWSPREVIOUS (the last one before the current), and AWSPENDING (exists only during rotation). You can attach up to 20 custom labels to versions, and two versions cannot share the same staging label, but one version can carry multiple labels. Labeled versions are never removed; unlabeled versions are considered deprecated and get cleaned up when there are more than 100.
Can I use AWS Secrets Manager with Lambda?
Yes, and it is the most common pattern. Two approaches: call GetSecretValue from the Lambda function directly (grant the execution role secretsmanager:GetSecretValue on the secret and kms:Decrypt on the key), or use the AWS Parameters and Secrets Lambda Extension, which caches the secret in the Lambda execution environment so you do not pay the API call cost or the latency on every invocation. The extension is the recommended pattern for cost and performance.
What are the limits of AWS Secrets Manager?
The documented limits: 65,536 bytes maximum per secret value; secret names of 1-512 alphanumeric and /_+=.@- characters; up to 20 staging labels on versions of a secret; deprecated (unlabeled) versions are removed when there are more than 100, but never versions created less than 24 hours ago; up to 10 filters in a list-secrets call. For per-account secret count quotas, check the AWS service quotas page — these have been adjusted upward historically and the current figure should be verified there rather than from memory.
Related Reading
- What is AWS KMS: Who Holds the Keys to Your Data
The service that encrypts every secret in Secrets Manager — how the key hierarchy works, what envelope encryption means, and when to use the AWS managed key versus your own. - What is AWS Security Hub in Plain English
The service that aggregates the security findings across your account — including the Config rules that check whether your secrets are configured to your compliance requirements. - What is Amazon Macie in Plain English
The service that scans S3 for sensitive data — the complement to Secrets Manager, catching the credentials that leaked into object storage rather than staying in the vault.
Revision note. Written September 2026, the specifics most likely to change are the partner list (which grows as new SaaS integrations are added), the per-account secret quota (which AWS has raised historically), and any future pricing adjustments — verify current figures against the AWS Secrets Manager pricing page before budgeting. Because you know AWS there were multipe memes which say how cost works in AWS. If you are moving credentials out of source code for the first time, the honest advice is that the hardest part is not the service; it is finding every place the old password has leaked into over the years, and you are doing the right thing by sorting that out now.