API key rotation for small teams
Every small team has a folder of keys older than the company's last two hires: the Stripe secret that predates the rebrand, the AWS access key in someone's .env from the prototype, a SendGrid key with full send rights that three people know by heart, a GitHub token with repo scope that outlived the contractor who made it. Nobody rotated them because nobody has ever shown them what rotation looks like when it doesn't break production.
This is the deferred-maintenance problem, not a knowledge problem. Password managers pushed password rotation into routine; API keys never got the same machinery, so they quietly become permanent. Meanwhile the blast radius grows: a key made for a weekend script now powers your invoicing. A key like that, leaked, doesn't just embarrass you — it mines crypto in your cloud account or emails your entire customer list. The fix is a boring quarterly ritual with a strict sequence: create the new key before you kill the old one, always. Sixty minutes, once a quarter, and the day a key leaks becomes an inconvenience instead of an incident. This pairs with the key-leak response runbook the same way backups pair with restore tests.
1. Build the key inventory (25 minutes, once)
Rotation starts the same way every good control does: you cannot rotate what you cannot list. One sitting, then it's a living document:
- Sweep the usual hiding places. Team password manager, the
.envfiles people actually run, CI/CD secret stores (GitHub Actions secrets, Vercel/Netlify/Railway env vars, Docker/Kubernetes secrets), server config files, the shared Google Doc someone made in year one, browser-stored postman collections, and the notes app on the founder's phone. The last two are where the oldest, widest keys live. - Then sweep the providers, not just your notes. Open the API-keys page of every provider you use — AWS IAM, Stripe, SendGrid, Twilio, OpenAI, GitHub, Cloudflare, your DNS registrar — and list every key that exists, not every key you remember creating. Providers are ground truth; your inventory is the diff. The keys that appear only on the provider side are the scary ones.
- Record four fields per key: what it's for, where it's used (system and file path), who or what owns it, and its scope/permissions. Scope is the field that turns a leaked key from a catastrophe into a shrug — a read-only analytics key that expires is a non-event.
- Date every key. Provider consoles show created/last-used timestamps. A key unused for 90 days is not an asset; it's an unlocked door nobody walks through. Delete those in step 5 — don't rotate them, retire them.
2. Decide per key: rotate, shrink, or retire
Not every key deserves rotation. The quarterly decision for each key is one of three moves:
- Retire keys with no confirmed use in the last quarter (verify in the provider's last-used column, not in memory). Deleting an unused key is the highest-yield security action in this whole checklist: zero downtime, zero migration, one less thing to leak.
- Shrink keys whose scope is wider than their job. The invoicing cron that only reads invoices does not need write. The CI job that deploys does not need IAM wildcard. Replace one wide key with two narrow ones while you're in there — the rotation is already open, the marginal cost is minutes.
- Rotate everything that stays: any key older than 90 days, any key known to more than one person, any key that ever appeared in a chat thread, ticket, screenshot, or commit — even one you "deleted." Git history is forever, which is why secret hygiene treats pushed secrets as leaked, always.
3. The no-downtime rotation sequence (the part nobody teaches)
Rotations break production in exactly one way: the old key dies while something still uses it. The sequence below makes that impossible, and it's the whole ritual in miniature:
- Step 1 — Create the new key with the narrowest scope that does the job. Note its prefix/ID. Do not touch anything else yet.
- Step 2 — Deploy the new key everywhere the old one lives: update the secret store, the
.envfiles, the CI variables, the cron host, the server config. Where multiple consumers share one key, deploy the new key to each in turn and verify each consumer before moving on — a test call, a dry run, a health check. The inventory from step 1 is your deployment list; anything you can't find a consumer for goes back to the provider page to be retired, not rotated. - Step 3 — Watch for stragglers. Give it one cron cycle and one deploy pipeline (usually a day; if you rotate on a Monday, revoke the following Monday). Then check the provider's last-used timestamp on the old key. Timestamp shows a hit after you deployed? Something still uses it — find it before step 4, not after.
- Step 4 — Revoke the old key. Now, and only now. The old key's last-used timestamp freezes, the log entry gets written, and the rotation is complete. A key that is revoked but whose consumers were never verified is how Saturday outages are manufactured.
The order is the safety property: create → deploy → verify → revoke. At every moment before the last step, both keys are live, so a missed consumer costs nothing but a log line.
4. The platforms that quietly hold half your keys
Small teams rotate the keys in their password manager and forget that the deploy platform is made of keys too:
- CI/CD variables (GitHub Actions secrets, GitLab CI variables, CircleCI contexts): these are copies of production credentials with their own access rules. Rotate the source key, then update the CI secret — and check who can read the secret. A CI secret readable by every repo in the org is one compromised dependency away from a supply-chain incident.
- Deploy platforms (Vercel, Netlify, Railway, Fly, Heroku): env vars per project, often copied from one project to the next by hand. Search across projects for the old key's prefix; platforms make cross-project drift easy and rotating one project while three others still hold the dead key is the classic follow-up outage.
- Server configs and cron hosts: the backup box and the crontab are where keys go to become immortal. Grep the usual config paths on every box in your inventory — not just the primary app server.
- Container images and build artifacts: if a key was ever baked into an image or a build log, treat it as leaked regardless of the calendar — rotation is the only cleanup that works, because you cannot un-bake a secret.
5. Kill the shared key while you're in there
The rotation session is the cheapest moment the team will ever have to fix key architecture, not just key age:
- One key per consumer, not one key per provider. If three systems use the SendGrid key, rotation day is when you split it into three keys. Now next quarter's rotation touches one system at a time, a leak's blast radius is one system, and the last-used timestamps tell you exactly which consumer is alive.
- Replace shared "team keys" with scoped, per-system keys. A key everyone shares is a password written on the whiteboard. The audit trail question "who used this key?" currently answers "yes."
- Move credentials out of chat, tickets, and docs. Every key found in Slack or a Google Doc during the step-1 sweep gets rotated and relocated to the password manager or secret store in the same session. The relocation is what stops the re-leak; the rotation alone just resets the clock on the same bad habit.
- Prefer provider features that make rotation automatic. OAuth-style tokens, short-lived credentials, and identity-based auth (workload identity, instance roles) remove the rotation problem class entirely. Every key you convert to auto-expiring is one line you delete from next quarter's checklist.
6. Third-party and vendor keys: the keys you don't control
Half the credentials in a small company's blast radius belong to other people's systems, and they rotate on their own schedule, not yours:
- Rotate what you issue to others, too. API keys you gave to a contractor, an integration partner, or a customer's webhook are in your inventory with an extra field: who holds it. Contractors rotate out of the company the same way employees do — their keys go through the offboarding checklist, not the quarterly ritual.
- Webhook signing secrets count. The secret that verifies your payment provider's webhooks is a key; rotate it on the provider's dual-secret schedule (most support two live secrets for exactly this create-deploy-verify-revoke dance).
- Know each provider's rotation mechanics before you need them. Five minutes per provider now: does it support two live keys? does the old key have a grace period? can scope be changed without reissuing? This is the difference between a 10-minute rotation and an outage. Log it in the vendor review.
- Credential-stuffing works both ways: your key to their API is their exposure to you. If a vendor is breached and discloses leaked credentials, your key on their systems is rotated that day — add "vendor breach news" as a trigger, not a quarterly wait.
7. The rotation log (turns a ritual into a control)
One file, appended every quarter. This is the document that makes the whole thing auditable — by you, by a customer's security reviewer, by the annual review:
- Per rotation, record: date, key (by name/prefix, never the value), action (rotated / retired / shrank), consumers updated, verification done, old key revocation confirmed. The revocation-confirmed line is the one auditors and incident retros look for first.
- Keep last-used timestamps from the provider console in the log — they're your proof that consumers moved over and your early-warning system for the stragglers you missed.
- Log the exceptions, not just the rotations. "Stripe key rotates on its own schedule per provider policy; verified 2026-Q3" is a complete and professional answer. An unexplained gap is where a postmortem starts.
- Feed one section up for free: "All N provider keys reviewed Q3; M retired, K shrank, J rotated, 0 exceptions" is a line your next enterprise buyer's questionnaire wants, ready-made from the questionnaire template.
8. Make it a calendar event, not a memory test
The ritual only survives if the calendar carries it:
- Quarterly, 60 minutes: sweep (10) → provider diff (10) → decisions (10) → rotations with the create-deploy-verify-revoke sequence (25) → log (5). Batch the easy ones; leave the two scariest keys (production DB, cloud root-adjacent) for a second pair of eyes if you have one.
- Event-driven rotations, regardless of calendar: staff or contractor departure, a key seen in a chat/screenshot/commit, a vendor breach disclosure, an endpoint device loss — these rotate immediately through the leak runbook, not at the next quarter boundary.
- Tie it to the existing maintenance rhythm. The same quarterly pass that checks backup restores and firmware can carry key rotation; one ops morning, three controls, one calendar entry.
- Automate what you can: provider APIs for key listing, a CI job that greps repos for key-shaped strings against the inventory, alerts on new key creation. The goal is not a zero-touch system — it's a system where the human session is decisions, not discovery.
9. Common failure modes (learned the hard way by someone, somewhere)
- Revoking before deploying. The single most common rotation outage. The sequence in section 3 exists to make this impossible; if you find yourself in a provider console about to delete the old key, stop and check the consumers first.
- Rotating the key but not the secret store. The password manager has the new key, CI still has the old one, and next quarter's sweep finds the ghost. One key, one source of truth, one owner.
- "It's internal, we'll rotate later." Internal keys leak through exactly two doors: people and logs. Both doors open from the inside.
- The forever grace period. Some providers let an old key linger in a "disabled but recoverable" state. Disabled is not deleted. Finish the revocation, confirm it in the log, close the tab.
10. Close the loop: the quarterly pass, the runbook, and the audit trail
- One page in the ops wiki (or one file in the repo) holds: the inventory, the rotation log, and the calendar recurrence. If it lives in someone's head, it's a ritual; if it lives in the repo, it's a control.
- The leak runbook stays one click away. The whole point of routine rotation is that the emergency path — leak response in the first 30 minutes — becomes rare and rehearsed, because everyone already knows where every key lives and how to replace it. The drill is the same sequence you've done twelve times, just faster and angrier.
- Ship the log line upward. The quarterly summary line goes into the annual review and the customer security questionnaire. Compliance reviews are mostly someone asking "do you actually do the things on your website?" — this is the file that answers.
- Remember the economics: 60 minutes per quarter to make the worst Tuesday of your year a 20-minute fix. The secrets checklist, the restore test, and this rotation live in the same ops morning — and that morning is the cheapest insurance the team will ever buy.