API Key Rotation Automation for Microservices
Table of Contents
- Why Manual Key Rotation Fails in Microservices
- The Five-Phase Zero-Downtime Rotation Framework
- Phase 1: Inventory and Classification
- Phase 2: Dual-Key Activation
- Phase 3: Staged Rollout
- Phase 4: Revocation
- Phase 5: Audit and Feedback
- Choosing a Secrets Management Layer
- AWS: Automating Rotation with Secrets Manager and Lambda
- Azure: Key Vault Rotation Policies and Function Apps
- Terraform: Managing Rotation as Infrastructure
- CI/CD Integration: Where Rotation Belongs (and Doesn't)
- Monitoring and Observability During Rotation
- Common Mistakes and What Most Guides Get Wrong
- 1. Rotating before the producer supports dual keys
- 2. The “test” step that doesn't actually test
- 3. Revoking too fast
- 4. Storing both keys in one unversioned field
- 5. Coupling rotation to deploys
- 6. Ignoring the provider's rate limits and quota policies
- Budget and Team-Size Recommendations
- Tier 1: Small team (1–5 engineers, up to 15 services)
- Tier 2: Mid-size team (5–20 engineers, 15–60 services)
- Tier 3: Enterprise (20+ engineers, 60+ services)
- Rotation Checklist: Before, During, and After
- Pre-Rotation Checklist
- During-Rotation Checklist
- Post-Rotation Checklist
- Frequently Asked Questions
- How often should API keys be rotated?
- What is zero-downtime API key rotation?
- Does AWS Secrets Manager rotate keys automatically?
- Can API key rotation be fully automated for third-party APIs?
- What is the difference between API keys and dynamic secrets?
- How do I prevent downtime when rotating API keys?
- Which compliance frameworks require API key rotation?
- How much does automated API key rotation cost?
- Start With the One Key That Hurts Most
At 2:47 AM on a Tuesday, an engineer pushes a .env file to a public GitHub repository. Before the commit is three minutes old, automated scanners have extracted the AWS access key and started launching GPU instances in your account. The billing alert arrives four hours later. The damage report lands sometime after that.
I've built credential management systems for companies that lived through this exact scenario. The painful lesson is always the same: a policy that says “don't leak keys” is not a defense. The only real defense is a system where keys are short-lived and routinely rotated, so a leaked credential expires before it can be weaponized.
This guide is a production playbook for automating API key rotation in microservices — the zero-downtime patterns for AWS, Azure, Terraform, and monitoring that most articles skip. You'll get a five-phase rotation framework, copy-paste Lambda code, a secret-manager comparison table, common failure modes, and cost breakdowns at three team sizes.
Why Manual Key Rotation Fails in Microservices
NIST Special Publication 800-57 recommends limiting the cryptoperiod of keys, and 90 days has become a practical default for API credentials. That sounds simple until you count how many keys a microservices platform actually holds. A 40-service platform typically has 300–600 secrets: database credentials, third-party API keys, service-to-service tokens, and cloud access keys. Asking a human to rotate 600 credentials by hand every quarter isn't a process — it's a hope.
Manual rotation fails in three specific ways. First, it's asynchronous: the person who owns a key is rarely the person who redeploys the consuming service, so the task waits for “the next deploy window” and slips for months. Second, it couples a security control to a release cycle that has its own priorities. Third, it produces no reliable audit trail — when the key is finally rotated, nobody can prove the old one has stopped working.
Automation flips this. You build a mechanism that issues, distributes, validates, and revokes keys on a schedule. More importantly, you build a mechanism that handles the failure modes: a new key that gets rejected, a downstream service that still holds the old key, or an external provider that only accepts a single active key. The rest of this guide is about exactly how to build that.
The Five-Phase Zero-Downtime Rotation Framework
Zero-downtime rotation isn't a single command. It's a five-phase sequence that treats key rotation like a production deploy: build the change, stage it, validate it, ship it, and then clean up. This is the framework I've used at companies rotating anywhere from 5 to 500 secrets, and it maps directly onto the rotation protocols used by AWS Secrets Manager and Azure Key Vault.
Phase 1: Inventory and Classification
You can't rotate what you can't see. Map every API key your platform uses: where it's stored, which services consume it, which provider issues it, and what it can access. A small team with 12 microservices should budget about one week for this — export secrets from your cloud consoles, cross-reference them with the env vars in your deploy configs, and flag anything you can't account for. Classify each key by two dimensions: who controls the producer (internal service or third-party API) and its blast radius (read-only vs. admin access). These two dimensions determine everything downstream — rotation cadence, whether zero-downtime rotation is even possible, and how much validation the new key needs.
Phase 2: Dual-Key Activation
Generate the new key while the old one remains active. This requires the producer to support at least two simultaneous keys: AWS IAM users support two access keys, Stripe supports multiple restricted keys, and most serious API providers offer rolling-key support. If the provider only allows one active key per account, you cannot do true zero-downtime rotation with that provider — you'll need a maintenance window, and you should schedule it during your lowest traffic hours. Store the new key as a new version in your secrets manager with a pending or AWSPENDING stage. Never overwrite the same version with the new value; versioning is what makes rollback possible.
Phase 3: Staged Rollout
Deploy the new key to a subset of consumers first. In a microservices environment, that means pointing a canary service or a single pod at the pending version and watching its error rate, latency, and auth failures for 15–60 minutes. If the new key fails, the blast radius is one service, not the entire platform. Once the canary is green, roll the pending key out to the remaining consumers — either by pushing new config or by having services pull the latest secret version at deploy time.
Phase 4: Revocation
Revocation is the irreversible step, and it should wait until the new key has been validated in production for a defined window — 24 hours is the floor; 7 days is comfortable for most platforms. Before revoking, confirm that no consumers are still using the old version by checking your authentication logs. Then revoke the old key at the provider, not just in your secrets manager. Deleting the value from your vault while the old key stays valid at the provider gives you a false sense of security.
Phase 5: Audit and Feedback
Record the rotation outcome: which version IDs were involved, how long each phase took, whether any step failed, and what the post-revocation audit logs show. Push these metrics into your observability stack so every subsequent rotation is measurable. The audit step is also where you decide whether to tighten the cadence — if the last incident took 6 hours to detect because the previous rotation was 11 months ago, a 30-day window is more appropriate than a 90-day one.
Choosing a Secrets Management Layer
The secrets manager is the backbone of automated rotation. It stores versions, triggers rotation, and exposes the current and pending values to consumers. But here's the honest truth: none of these tools rotate keys for you. They give you a place to store the key, a scheduler to trigger the event, and an API to fetch versions. The rotation logic itself — generating the key, calling the provider, testing it, revoking the old one — is always your responsibility.
| Tool | Native Rotation | Multi-Cloud | Pricing | Dynamic Secrets | Best For |
|---|---|---|---|---|---|
| AWS Secrets Manager | Yes (Lambda hooks) | No | $0.40/secret/month + $0.05 per 10k API calls | No | AWS-centric platforms |
| Azure Key Vault | Yes (rotation policies) | No | $0.03 per 10k operations (Standard) | No | Azure-centric platforms |
| Google Secret Manager | Scheduler only (no built-in rotation logic) | No | $0.06 per active secret version/month | No | GCP-centric platforms |
| HashiCorp Vault | Via auth method plugins | Yes | OSS free; Enterprise depends on contract | Yes | Multi-cloud and dynamic DB credentials |
| Doppler | Limited (integration-based) | Yes | ~$18/user/month on paid plans | No | Small teams that want developer UX |
How do you choose? If your platform runs entirely on AWS, AWS Secrets Manager is almost always the right call — the Lambda integration is mature and the IAM model fits your existing identity system. Azure Key Vault makes sense in the same way for Azure shops. If you run across two clouds or need ephemeral credentials for databases, HashiCorp Vault is worth the operational complexity. And if you have a team of 3–5 engineers with a .env-driven development workflow, starting with a managed secrets manager plus a simple scheduled rotation job beats building a Vault cluster.
AWS: Automating Rotation with Secrets Manager and Lambda
AWS Secrets Manager's rotation protocol is a four-step state machine: createSecret, setSecret, testSecret, and finishSecret. Secrets Manager invokes your Lambda for each step in order, and the Lambda is responsible for managing the AWSPENDING and AWSCURRENT version stages. This is the cleanest implementation of zero-downtime rotation in any cloud today, because the new key coexists with the old one until the final promotion step. The official rotation docs cover the state machine, but the practical details are where implementations go wrong.
import boto3
import json
import logging
import secrets
logger = logging.getLogger()
logger.setLevel(logging.INFO)
client = boto3.client('secretsmanager')
def lambda_handler(event, context):
try:
step = event['Step']
token = event['ClientRequestToken']
secret_id = event['SecretId']
metadata = client.describe_secret(SecretId=secret_id)
if not metadata['RotationEnabled']:
raise Exception(f'Secret {secret_id} has rotation disabled')
versions = metadata['VersionIdsToStages']
if token not in versions:
raise Exception(f'Version {token} not found for secret {secret_id}')
if 'AWSPENDING' in str(versions.get(token, [])):
if step == 'createSecret':
create_secret(secret_id, token)
elif step == 'setSecret':
set_secret(secret_id, token)
elif step == 'testSecret':
test_secret(secret_id, token)
elif step == 'finishSecret':
finish_secret(secret_id, token)
logger.info('Step %s complete for %s', step, secret_id)
except Exception as err:
logger.exception('Rotation failed for %s at step %s',
event.get('SecretId'), event.get('Step'))
raise err
def create_secret(secret_id, token):
new_key = 'sk_live_' + secrets.token_urlsafe(32)
payload = json.dumps({'api_key': new_key, 'status': 'pending'})
client.put_secret_value(
SecretId=secret_id,
ClientRequestToken=token,
SecretString=payload,
VersionStages=['AWSPENDING']
)
def set_secret(secret_id, token):
# If consumers pull secrets at deploy time, this step is a no-op.
# If you push config to services, deploy the pending value here.
pass
def test_secret(secret_id, token):
pending = client.get_secret_value(
SecretId=secret_id,
VersionId=token,
VersionStage='AWSPENDING'
)
api_key = json.loads(pending['SecretString'])['api_key']
status = call_downstream_api(api_key)
if status != 200:
raise Exception(f'New key rejected by downstream: HTTP {status}')
def finish_secret(secret_id, token):
metadata = client.describe_secret(SecretId=secret_id)
current_version = None
for version, stages in metadata['VersionIdsToStages'].items():
if 'AWSCURRENT' in stages and version != token:
current_version = version
client.update_secret_version_stage(
SecretId=secret_id,
VersionStage='AWSCURRENT',
MoveToVersionId=token,
RemoveFromVersionId=current_version
)Three details make or break this implementation. First, create_secret must never touch the AWSCURRENT version — if the rotation fails before finish_secret, the old key has to remain valid. Second, test_secret has to make a real authenticated call against the downstream API. A test that just decodes the secret string gives you false confidence and lets broken rotations silently propagate. Third, the Lambda's IAM role needs secretsmanager:PutSecretValue, secretsmanager:DescribeSecret, and secretsmanager:UpdateSecretVersionStage scoped to the specific secret ARN — don't grant * on secretsmanager and call it a day.
On the consumer side, the cleanest pattern is pull-based: services fetch the AWSCURRENT version at startup and cache it in memory with a short TTL. This means no push infrastructure, no restart orchestration, and no config drift. Services simply pick up the new key on their next deploy or cache refresh. The push pattern — where rotation triggers a service restart — is necessary only when consumers cache credentials in ways that outlive the rotation window.
Azure: Key Vault Rotation Policies and Function Apps
Azure's approach is similar but the mechanics differ. Key Vault stores the secret, and a rotation policy triggers an Azure Function App on a schedule. The function generates the new key, updates the vault, and the old version stays available because Key Vault keeps version history by default. Unlike AWS's four-step state machine, Azure leaves the state management to you — your function owns the full lifecycle, which gives you flexibility and more room to make mistakes.
#!/usr/bin/env bash
# Create the initial secret
az keyvault secret set \
--vault-name "prod-vault" \
--name "stripe-api-key" \
--value "sk_live_initial"
# Attach a rotation policy: notify at 30 days, expire at 90 days
az keyvault secret rotation set-policy \
--vault-name "prod-vault" \
--name "stripe-api-key" \
--lifetime-actions "type=rotate,action=notify,timeAfter=P30D" \
--expires-in P90DIn practice, the rotation policy alone isn't enough for API keys — you still need a TimerTrigger function that calls the provider's API to generate a new key, writes it to Key Vault as a new version, and verifies it against the downstream service. A Python Function App with a TimerTrigger works like this: the timer fires every 30 days, the function checks the age of the current secret version, generates a new key via the provider, updates the vault, and emits a metric on success or failure.
One Azure-specific failure mode I see repeatedly: teams rotate the secret value but forget that Application Settings in their App Services or AKS SecretProviderClass references are point-in-time snapshots. When Key Vault rotates, running services that loaded the secret at startup keep the old value until they restart. If your services load secrets at startup, rotation and redeployment are coupled — account for it in the rollout phase or switch to a pull-based client that watches for version changes.
Terraform: Managing Rotation as Infrastructure
Rotation automation should be declarative. If a new engineer joins and needs to know how key rotation works, the answer should be “read the Terraform,” not “ask Dave.” Terraform manages the secret, the rotation Lambda, and the schedule in one place.
resource "aws_secretsmanager_secret" "stripe" {
name = "stripe-live-key"
}
resource "aws_secretsmanager_secret_rotation" "stripe" {
secret_id = aws_secretsmanager_secret.stripe.id
rotation_lambda_arn = aws_lambda_function.key_rotation.arn
rotation_rules {
automatically_after_days = 30
}
}
# The initial value is needed to bootstrap the secret, but once
# rotation is enabled the runtime owns the value.
resource "aws_secretsmanager_secret_version" "stripe_initial" {
secret_id = aws_secretsmanager_secret.stripe.id
secret_string = var.initial_stripe_key
lifecycle {
ignore_changes = [secret_string]
}
}The ignore_changes block is the part most teams miss. Without it, the next terraform plan diffs the rotated value against the value in your state file, and either a teammate “helpfully” applies the change and rolls the key back, or the plan produces perpetual noise. Once rotation is automated, the runtime owns the secret value, and Terraform's job ends after the initial bootstrap.
The same principle applies on Azure with azurerm_key_vault_secret — set the initial value, then ignore_changes = [value]. On multi-cloud platforms, keep the Terraform state in one place and the secret values in each cloud's vault; don't put secrets in the state file itself. Use a backend that encrypts state at rest, and treat the state file as being only one step below the secrets themselves in sensitivity.
CI/CD Integration: Where Rotation Belongs (and Doesn't)
Rotation does not belong in CI. If your rotation runs as a step inside a GitHub Actions pipeline or a Jenkins job, it's coupled to your release cadence, and it will fail silently on days when nobody pushes code. Rotation belongs in the cloud's scheduler, as we covered. CI/CD's real job is delivering the consumers that read the new key version.
The pattern that works: every service builds with a startup step that fetches the latest secret version from the secrets manager and injects it as an environment variable or mounted file. In GitHub Actions, that means using the official AWS or Azure actions to fetch secrets at deploy time and reference them as env vars. No rotation logic in the pipeline, no hardcoded keys in the repo, no drift between what CI thinks the key is and what the secrets manager holds. If you need to restart services after rotation, wire an EventBridge rule to the RotationFinished event that publishes to an SNS topic — your services' orchestration layer subscribes and triggers redeployments.
Monitoring and Observability During Rotation
You need to see a rotation happen before you can trust it. The three metrics that matter are key age, rotation outcome, and old-key usage after revocation. Here's how to emit them:
import boto3
from datetime import datetime, timezone
cloudwatch = boto3.client('cloudwatch')
def emit_key_age_metric(secret_name, created_date):
age_days = (datetime.now(timezone.utc) - created_date).days
cloudwatch.put_metric_data(
Namespace='CredentialLifecycle',
MetricData=[{
'MetricName': 'ApiKeyAgeDays',
'Value': age_days,
'Dimensions': [{'Name': 'Secret', 'Value': secret_name}]
}]
)Key age is the early-warning signal. If your rotation window is 30 days, an age alert at 35 days tells you the scheduler died, the Lambda errored, or the provider rejected the new key. Rotation outcome is the second signal: count successful rotations vs. failures per secret, and alert on any failure that isn't followed by a successful retry within an hour. The third signal is post-revocation usage. After you revoke an old key, query the provider's audit logs for that key ID and alert if anything authenticates with it — that's the definitive test of whether your blast radius reduction actually worked.
During rotation, logging discipline matters more than ever. Never log the secret value, the full event payload, or the Lambda response — the SecretString appears in CloudWatch if you log the event object directly. Log version IDs, step names, durations, and status codes only. For deeper runtime visibility into how your services consume secrets, pairing rotation metrics with eBPF security observability for Kubernetes gives you a picture of which service instances are actually reading which secret versions — without touching application code.
Common Mistakes and What Most Guides Get Wrong
After watching dozens of teams implement rotation, these are the failures I see repeatedly.
1. Rotating before the producer supports dual keys
The assumption that every API provider lets you have two active keys is dangerous. Some providers — particularly smaller SaaS tools — allow only one secret key per account. If you generate a new key and revoke the old one in the same script, you get a hard outage the moment the provider processes the revocation. Read the provider's docs before building the rotation. If the provider is single-key, schedule maintenance windows instead of pretending zero-downtime is possible.
2. The “test” step that doesn't actually test
I've audited rotation functions where testSecret simply decoded the pending secret and logged “success.” That's not a test. The test step must make a real authenticated call against the downstream service and fail the rotation if the response is not what's expected. A fake test step turns your rotation pipeline into a key generator that occasionally revokes a key nobody verified.
3. Revoking too fast
The old key's grace window exists for a reason: caching. Services cache credentials at the process level, connection pool level, and HTTP client level. If you revoke the old key 30 seconds after promoting the new one, you will break services that cached the old key and haven't refreshed yet. A 24-hour minimum overlap is the floor; 7 days is safer for platforms with long-lived workers.
4. Storing both keys in one unversioned field
Some teams store the old and new keys as comma-separated values in a single secret, then parse them in application code. This destroys the secrets manager's versioning, makes rollback impossible, and leaks one key's lifecycle into another. Store each key as its own version and let the secrets manager handle stage transitions.
5. Coupling rotation to deploys
If your rotation “happens with the next release,” it happens quarterly at best and never at worst. Rotation has to run on its own schedule, independent of feature releases. This is why scheduler-driven rotation beats CI-driven rotation — it removes the human dependency on remembering to trigger it.
6. Ignoring the provider's rate limits and quota policies
Every major API provider has rate limits on their key-management endpoints, and some cap the number of keys you can create per account. Your rotation Lambda can hit those limits if it runs across many secrets at once. Spread rotation schedules randomly across the window (a 30-day rotation doesn't mean all keys rotate at 00:00 on day 30) and add jitter to the rotation trigger. The OWASP Secrets Management Cheat Sheet covers the broader risk model if you want the full picture.
Budget and Team-Size Recommendations
What you should build depends on who you are. Here's the honest breakdown by team size, based on what I've seen work.
Tier 1: Small team (1–5 engineers, up to 15 services)
Budget: under $300/month. Don't build a platform — buy cloud-native automation. If you're on AWS, create one rotation Lambda per external provider, store all keys in Secrets Manager, and set a 90-day rotation window initially. Use pull-based secret fetching in your services so no push infrastructure is needed. Implementation time: 3–5 days for the first provider's rotation, then faster for each additional one. For a 3-person SaaS team with a $500 monthly security budget, this tier is the right investment; spend the remaining budget on a secrets scanner for your repos instead of over-engineering rotation.
Tier 2: Mid-size team (5–20 engineers, 15–60 services)
Budget: $300–$1,500/month. Move all secrets and rotation config into Terraform, tighten the rotation window to 30 days, and add alerting on key age and rotation failures. One engineer owns credential lifecycle as a permanent responsibility. Implement the EventBridge-to-SNS restart pipeline so consumers refresh automatically. Implementation time: 2–3 weeks for the full inventory plus automation. If you're also building out platform tooling, review how rotation fits into your broader internal developer platform migration so it doesn't become a bolt-on.
Tier 3: Enterprise (20+ engineers, 60+ services)
Budget: $1,500+/month. Run HashiCorp Vault for dynamic database credentials and rotate API keys through cloud secret managers. Set SLOs: p95 rotation duration under 24 hours, zero failed rotations that exceed one hour without alerting. Build a full event-driven pipeline where rotation events trigger consumer restarts automatically, and hold a monthly audit that reviews key-age distributions and post-revocation usage. Enterprise teams should also watch out for the structural patterns that break rotation initiatives — the same anti-patterns documented in our analysis of platform engineering antipatterns apply to credential systems.
Rotation Checklist: Before, During, and After
Pre-Rotation Checklist
- Inventory every API key: location, consumer, provider, blast radius, expiry.
- Confirm each provider supports two simultaneous active keys; flag single-key providers.
- Write the rotation function with a real test step that calls the downstream API.
- Deploy the rotation function to staging and run it against staging credentials with production-shaped permissions.
- Verify monitoring dashboards emit key age, rotation outcome, and post-revocation usage metrics.
- Set the rotation schedule with jitter so not all keys rotate at the same instant.
During-Rotation Checklist
- Confirm the old key remains valid after
createSecret. - Watch error rates and auth failures on the canary consumer before rolling out.
- Verify the new key authenticates against the downstream service.
- Leave the old key active for the full grace window (24 hours minimum, 7 days recommended).
Post-Rotation Checklist
- Revoke the old key at the provider, not just in your vault.
- Query provider audit logs for old-key usage after revocation.
- Update the runbook with actual rotation duration and any failures.
- Adjust the rotation window based on incident detection time.
Frequently Asked Questions
How often should API keys be rotated?
For most production platforms, 30–90 days is the right range. The NIST SP 800-57 guidance on cryptoperiods recommends limiting key lifetimes based on security impact, and 90 days is a widely accepted default for API credentials. If your compliance requirements (SOC 2, PCI-DSS, ISO 27001) specify a cadence, follow the strictest one. Tighten to 30 days if you've had a leak incident, handle highly sensitive data, or work in an environment with high employee turnover.
What is zero-downtime API key rotation?
Zero-downtime rotation is the process of replacing an API key without causing any interruption to services that use it. It works by having the old key and the new key active simultaneously for a grace period: generate the new key, deploy it to consumers, validate it in production, and only then revoke the old key. This requires the API provider to support two simultaneous active keys per account. If a provider only allows one key, true zero-downtime rotation isn't possible for that integration.
Does AWS Secrets Manager rotate keys automatically?
AWS Secrets Manager provides the infrastructure for rotation but not the rotation logic itself. When you enable rotation on a secret, Secrets Manager invokes a Lambda function that you write to generate the new credential, test it, and promote it. The built-in templates handle credentials for databases like RDS and Redshift, but for third-party API keys you must implement the provider-specific logic in your own Lambda function.
Can API key rotation be fully automated for third-party APIs?
Yes, if the third-party provider offers an API for key management and supports two simultaneous active keys. Your rotation function calls the provider's API to create a new key, stores it in your secrets manager, tests it against the provider's service, and revokes the old key after the grace window. Providers like Stripe, Twilio, and OpenAI can be rotated this way. For providers without a key-management API, you need a manual step or a scheduled reminder.
What is the difference between API keys and dynamic secrets?
API keys are long-lived credentials issued by a provider, while dynamic secrets are short-lived credentials generated on demand — typically by HashiCorp Vault — that expire automatically after minutes or hours. Dynamic secrets are ideal for database credentials in ephemeral environments because they eliminate the concept of a leaked key. API key rotation is the technique used when dynamic secrets aren't available, which is the case for most third-party SaaS providers. The two approaches are complementary.
How do I prevent downtime when rotating API keys?
Apply the five-phase framework: generate the new key while the old one stays active, deploy the new key to a canary consumer first, validate it against the downstream service, wait a grace period of at least 24 hours, and only then revoke the old key. Make your services pull secrets from the secrets manager at startup or on a short cache TTL rather than embedding values at build time. The most common cause of rotation downtime is revoking the old key before every consumer has picked up the new one.
Which compliance frameworks require API key rotation?
SOC 2, PCI-DSS, ISO 27001, and NIST 800-53 all include requirements around credential management that rotation satisfies. SOC 2's logical access controls require periodic review and revocation of credentials, PCI-DSS requires changes to default credentials and cryptographic key changes on a defined cycle, and NIST 800-57 explicitly limits key cryptoperiods. Automated rotation gives you an audit trail that proves compliance in a way that manual processes never can.
How much does automated API key rotation cost?
AWS Secrets Manager costs $0.40 per secret per month plus $0.05 per 10,000 API calls, so a platform with 100 secrets pays about $40/month before Lambda compute costs. Azure Key Vault charges $0.03 per 10,000 operations. The main cost is engineering time: a small team can implement rotation for one provider in 3–5 days, which is the dominant expense at any budget tier. Most of the cost is writing and testing the rotation functions, not the infrastructure that runs them.
Start With the One Key That Hurts Most
Pick the single most dangerous key in your infrastructure — the one with the widest blast radius and the weakest current lifecycle — and automate its rotation by the end of the week. Not all 600 secrets. One. Log into your cloud account, create the secret, write the rotation Lambda, set the 30-day timer, and wire the age metric into your monitoring. That one win proves the pattern, gives you a working template for every other key, and closes the window on the attack that keeps security teams up at night. The leaked key in that public repo can sit there indefinitely once it's rotated — and that's the entire point.


