For an OpenAI or Anthropic API key that an AWS Lambda function reads, a Parameter Store SecureString in the standard tier does the job with no storage charge, as long as the function caches what it reads. AWS Secrets Manager adds managed rotation, cross-Region replicas and 64 KB values for $0.40 per secret per month. And on AWS, you may not need a stored key at all.
The choice usually gets made on the wrong feature. Rotation, the thing Secrets Manager is known for, does not reach either LLM provider, while the limit that actually breaks production is Parameter Store's default of 40 reads per second, which a function reading two keys per request passes at 21 requests per second. Since May 2026, OpenAI and Anthropic both offer workload identity federation that accepts short-lived tokens signed by AWS STS, which removes the stored key entirely.
Every number below follows one app: HelpDesk AI, a support chatbot on AWS Lambda in us-east-1 that calls both OpenAI and Anthropic, serves 3 million requests a month and peaks at 50 requests per second.
The Fastest Way to Price Your Own Workload
Enter your secret count, reads per secret per day and peak reads per second into the AWS Secrets Manager Cost Calculator. It prices both services from AWS list prices, switches Parameter Store to higher throughput once your peak passes 40 reads per second, and flags values that will not fit either service. It estimates from your inputs; it does not read your AWS bill. With HelpDesk AI's two keys read on every request, it lands on $30.80 a month for Secrets Manager and $30.00 for Parameter Store.

That near-tie is the first surprise: Parameter Store is only free while you stay under its throughput default.
What Each Option Gives an API Key
The table compares the two Parameter Store tiers, Secrets Manager and the federated option covered later, using AWS's service quotas, the Secrets Manager quotas and the us-east-1 price lists AWS published on September 11 and October 8, 2026, all checked October 22, 2026.
| Option | Max value | Default read limit | Managed rotation | Cross-Region copies | Cross-account access | Storage price | Read price |
|---|---|---|---|---|---|---|---|
| Parameter Store standard | 4 KB | 40 TPS, shared by GetParameter, GetParameters and GetParametersByPath | No | No | No | Free (10,000 per Region) | Free; $0.05 per 10,000 with higher throughput |
| Parameter Store advanced | 8 KB | Same 40 TPS | No | No | Yes, through AWS RAM | $0.05 per parameter per month | $0.05 per 10,000 |
| AWS Secrets Manager | 64 KB | 10,000 GetSecretValue per second | Yes, for some services | Yes, each replica billed as a secret | Yes, resource policies | $0.40 per secret per month | $0.05 per 10,000 |
| No stored key (STS federation) | n/a | n/a | Not needed | Not needed | IAM role per workload | None | None |
Both services keep up to 100 versions of a value, and both encrypt with AWS KMS. The default AWS managed keys carry no monthly fee; a customer managed key costs $1 a month plus $0.03 per 10,000 requests after 20,000 free requests a month, according to the AWS KMS pricing page.
Why Rotation Rarely Decides It for LLM Keys
Secrets Manager rotates a secret in one of three ways, per its rotation guide. Managed rotation covers Amazon RDS, Aurora, DocumentDB and Redshift credentials plus ECS Service Connect certificates. Managed external secrets cover a fixed list of partners: BigID, Cisco, Confluent Cloud, Databricks, Datadog, GitLab, Jenkins, MongoDB Atlas, Netskope, Paddle, Salesforce, Snowflake, SonarQube and Twilio. Everything else needs a rotation Lambda function that you write.

Neither OpenAI nor Anthropic is on that list as of October 22, 2026, and the two providers differ on whether a rotation function is even possible. OpenAI's Admin API can create a project service account and returns its new API key, with an optional expires_in_seconds, so a rotation Lambda for OpenAI keys is buildable. Anthropic's Admin API reference lists only list, retrieve and update operations for API keys, with no create endpoint, so a Claude key still has to be created by a person in the Claude Console.
For HelpDesk AI, that means Secrets Manager's $0.40 buys a rotation slot it would fill with custom code for one key and could not fill at all for the other.
Where the Bill and the Throttling Come From
The read path costs more than storage. A Lambda function that fetches both keys on every request makes 6 million reads a month. On Secrets Manager each read is a billable GetSecretValue call. On Parameter Store, HelpDesk AI's 50-request peak becomes 100 reads per second, well past the 40 TPS default, so requests start failing with ThrottlingException until you turn on higher throughput.
Higher throughput is a setting for the whole account and Region, not for one parameter, according to the Parameter Store throughput guide. It raises GetParameter to 10,000 transactions per second, and once it is on, every interaction is billed at $0.05 per 10,000, including standard parameters. A GetParameters call that returns two values counts as one transaction against the limit but two billable interactions, per the Systems Manager pricing page.
A five-minute cache changes the math. This script prices HelpDesk AI with and without one:
Python# Monthly cost of two LLM keys for 3M Lambda requests, us-east-1 list prices (Oct 2026). SECRET_MONTH, PER_10K = 0.40, 0.05 # same $0.05/10k for Secrets Manager calls KEYS, REQUESTS = 2, 3_000_000 # and Parameter Store higher-throughput interactions WARM_ENVS, TTL = 25, 300 # environments kept warm all month, cache seconds uncached = KEYS * REQUESTS cached = WARM_ENVS * KEYS * (30 * 86_400 // TTL) api = lambda reads: reads / 10_000 * PER_10K rows = [ ("Secrets Manager, no cache", KEYS * SECRET_MONTH + api(uncached)), ("Parameter Store, no cache (over 40 TPS)", api(uncached)), ("Secrets Manager, 300 s cache", KEYS * SECRET_MONTH + api(cached)), ("Parameter Store, 300 s cache", 0.0), ] print(f"reads/month: {uncached:,} uncached, {cached:,} cached") for name, usd in rows: print(f"{name:<42}${usd:>6.2f}")
textreads/month: 6,000,000 uncached, 432,000 cached Secrets Manager, no cache $ 30.80 Parameter Store, no cache (over 40 TPS) $ 30.00 Secrets Manager, 300 s cache $ 2.96 Parameter Store, 300 s cache $ 0.00
The cached figure assumes 25 execution environments stay warm all month, each refreshing both keys once every 300 seconds, which overstates a real month. The calculator gives the same totals for both cases. One caveat for the free row: a cold-start burst still reads once per new environment, so 30 environments starting in the same second ask for 60 reads. Fetching both keys in a single GetParameters call halves that.
How to Cache the Key in Lambda
AWS ships the AWS Parameters and Secrets Lambda Extension, a layer that serves both services from a local cache. Your code sends a GET request to localhost:2773 with the X-Aws-Parameters-Secrets-Token header set to AWS_SESSION_TOKEN. The cache lifetime is set by SSM_PARAMETER_STORE_TTL and SECRETS_MANAGER_TTL, which default to 300 seconds, the maximum. The current layer ARN sits in the public parameter /aws/service/aws-parameters-and-secrets-lambda-extension/x86/latest.
If you would rather not add a layer, the same cache takes a few lines of boto3. First, store both keys as SecureString parameters:
Bashaws ssm put-parameter --name /helpdesk-ai/prod/openai-api-key \ --type SecureString --value 'sk-proj-REPLACE_ME' --tier Standard aws ssm put-parameter --name /helpdesk-ai/prod/anthropic-api-key \ --type SecureString --value 'sk-ant-api03-REPLACE_ME' --tier Standard
Then read both in one call and keep them for 300 seconds:
Python# Read both LLM keys with one GetParameters call and keep them for 300 seconds, # the longest TTL the AWS Parameters and Secrets Lambda Extension allows. import time import boto3 TTL_SECONDS = 300 NAMES = ["/helpdesk-ai/prod/openai-api-key", "/helpdesk-ai/prod/anthropic-api-key"] ssm = boto3.client("ssm", region_name="us-east-1") _cache = {"expires": 0.0, "keys": {}} def llm_keys(now=None): now = time.monotonic() if now is None else now if now >= _cache["expires"]: resp = ssm.get_parameters(Names=NAMES, WithDecryption=True) _cache["keys"] = {p["Name"]: p["Value"] for p in resp["Parameters"]} _cache["expires"] = now + TTL_SECONDS return _cache["keys"]
We ran both against moto 5.2.4, a local AWS mock, rather than a real account, and replayed 1,000 requests spread over 10 minutes through one warm environment:
textrequests: 1000, GetParameters calls: 2 keys loaded: ['anthropic-api-key', 'openai-api-key']
Two calls instead of 2,000. Keep module-level state like _cache outside the handler so it survives between invocations, and remember that a changed key takes up to 300 seconds to reach every environment. Scope the function's role to ssm:GetParameters on those two parameter ARNs; the AWS IAM Policy Generator writes that statement.
Skip the Stored Key With STS Federation
AWS announced IAM outbound identity federation on November 19, 2025. The STS GetWebIdentityToken API returns a JWT signed by AWS that names the caller's IAM role, valid for 60 to 3,600 seconds (300 by default), per the STS API reference. An outside service can verify that token against your account's public keys, so it can trust your Lambda function without a shared secret.
Anthropic launched Workload Identity Federation for the Claude API on May 4, 2026, and OpenAI released workload identity federation on May 26, 2026, according to each company's changelog. Both document tokens from GetWebIdentityToken as a supported source, and Anthropic's AWS guide names Lambda, EC2, ECS and EKS. An organization admin registers your account's issuer URL and maps the function's IAM role to a service account, then the SDK exchanges the AWS token for a provider token that expires in minutes and refreshes it on its own. AWS lists IAM, which includes outbound federation, at no additional charge.
Python# No API key anywhere: AWS STS signs a short-lived JWT for the Lambda's IAM # role, and each SDK trades it for its own short-lived access token. import os import boto3 import anthropic import openai from anthropic import WorkloadIdentityCredentials sts = boto3.client("sts", region_name="us-east-1") # regional endpoint only def aws_jwt(audience, alg): return lambda: sts.get_web_identity_token( Audience=[audience], SigningAlgorithm=alg, DurationSeconds=300 )["WebIdentityToken"] claude = anthropic.Anthropic(credentials=WorkloadIdentityCredentials( identity_token_provider=aws_jwt("https://api.anthropic.com", "RS256"), federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"], organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"], service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"], )) gpt = openai.OpenAI(workload_identity={ "identity_provider_id": os.environ["OPENAI_IDENTITY_PROVIDER_ID"], "service_account_id": os.environ["OPENAI_SERVICE_ACCOUNT_ID"], "provider": {"token_type": "jwt", "get_token": aws_jwt("https://api.openai.com/v1", "ES384")}, })
The environment variables hold IDs, not credentials: none of them works without a token AWS signed for that role. We confirmed both clients build with anthropic 2.1.0, openai 3.36.1 and boto3 1.43.117. The token exchange itself needs the console setup on both providers, which we did not run end to end, so test it in a staging account first. The audiences and signing algorithms come from each provider's AWS guide.
The setup has three AWS steps: turn on outbound federation once per account with aws iam enable-outbound-web-identity-federation, give the function's role sts:GetWebIdentityToken, and limit that permission with an sts:IdentityTokenAudience condition, as OpenAI's guide shows. Run the policy through the IAM Policy Analyzer to catch a missing condition.
Common Errors
ThrottlingException from GetParameter or GetParameters. You passed 40 transactions per second in that account and Region. Cache the value, combine keys into one GetParameters call, or turn on higher throughput and accept the per-read charge.
ParameterNotFound. The name must match exactly, including the leading slash in /helpdesk-ai/prod/openai-api-key, and the client must point at the Region where you created the parameter.
OutboundWebIdentityFederationDisabledException. Outbound federation is off for the account, which is the default. Run aws iam enable-outbound-web-identity-federation once.
'STS' object has no attribute 'get_web_identity_token'. Anthropic's AWS guide gives two causes: a boto3 release that predates the API, or a client on the global STS endpoint. Upgrade boto3 and pass region_name.
When Not to Drop the Key
Federation covers workloads that hold an AWS identity. A developer laptop, a CI job outside AWS, or a third LLM provider without federation still needs a stored key, so keep those in Parameter Store and scan repositories for the ones that leaked into code with the Secret Scanner. Federation is also only as strong as the IAM role behind it: anyone who can assume that role can now call both APIs.
Which One to Pick
A Lambda function calling only OpenAI or Anthropic: use STS federation and store nothing.
Other API keys in one Region: use Parameter Store SecureString in the standard tier with a 300-second cache. It is free until you need higher throughput.
Database credentials, partner keys such as Datadog, Twilio or Snowflake, a disaster-recovery copy in us-west-2, cross-account access or values over 8 KB: use Secrets Manager. That is what the $0.40 a month buys.
Any of the above with no cache: fix the cache first. At HelpDesk AI's traffic it is the difference between $30.80 and $2.96 a month, or between throttled requests and none.
Conclusion
For LLM API keys on AWS, the read path decides the choice, not rotation. Neither OpenAI nor Anthropic is on Secrets Manager's managed rotation lists, so its $0.40 per secret a month mostly buys replicas, cross-account access and room for larger values. A Parameter Store SecureString in the standard tier holds the same key for free, and a 300-second cache keeps HelpDesk AI's steady-state reads far below the 40-per-second default that would otherwise throttle it at its 50-request peak.
The bigger change is that a Lambda function calling only OpenAI and Anthropic no longer needs a stored key. With workload identity federation, available from both providers since May 2026, the IAM role becomes the thing to protect, and Parameter Store stays for the keys federation cannot reach: developer laptops, CI jobs outside AWS and providers without federation.
Start with the numbers you already have. Price your secret count, read rate and peak in the cost calculator, add the cache, and only then decide whether Secrets Manager's extra features are worth $0.40 a secret.
Related DevToolLab Tools
- AWS Secrets Manager Cost Calculator - price your own secret count, read rate and peak against both services before you migrate.
- AWS IAM Policy Generator - write the
ssm:GetParametersorsts:GetWebIdentityTokenstatement for the function's role. - IAM Policy Analyzer - flag a statement on
Resource: "*"with no Condition block, which is how the STS permission looks before you add the audience check. - Secret Scanner - find OpenAI and AWS keys pasted into code or config before you move them into a store.
