Monthly key rotations: the small script that stopped our staging leaks (and the restart that taught me humility)

I automated monthly rotation of staging API keys. It stopped accidental long-lived leaks—until a rotation restarted a worker and crashed a pipeline. Here's what I actually built and why.

Written by: Arjun Malhotra

Person typing on a laptop with code visible on the screen
Photo by Sincerely Media on Unsplash

It was a Tuesday, and a junior dev pinged our on-call channel: “Hey — found a secret in a public gist. Possibly ours?” I remember the small, helpless feeling — the token belonged to our staging Razorpay account and had been valid for three months. Nobody knew how it got out. The gist had seen a few forks and a PR; one click and an attacker could replay webhooks for fun or profit.

We were lucky: it hit staging, not production. But luck is not a strategy.

We already used a secret manager for production. Staging was messy: long‑lived API keys copied into config files, a couple of deploy scripts that still read plain files, and a few developers who occasionally pasted keys into temporary scripts. I decided to stop treating staging like a sandbox and make it a little more hostile to leaks.

What I built (short version)

Why monthly, not daily Daily rotation is ideal in theory, terrible in practice. Providers rate‑limit key creation. Long‑running jobs or third‑party SDKs sometimes cache tokens aggressively. For our team (a 20‑person startup in Bengaluru with a tight infra budget), monthly rotation reduced blast radius significantly while keeping operational complexity low. It was cheap security — literally ₹0 in service fees, a few hours to build, and a ₹300 VPS runner we already used for CI jobs.

Implementation details that actually matter

The failure that mattered Three weeks after we rolled it out, a monthly rotation triggered an outage. Our long‑running payment reconciliation worker used a third‑party SDK that cached API credentials for the lifetime of the process. The rotation replaced the key in Vault and the web processes reloaded fine. The worker did not. It kept retrying with invalid credentials, and the backlog exploded until the queue filled.

We had assumptions baked into the script:

Fixes I had to make (and why I felt foolish)

Tradeoffs I accepted

What this changed

A real limitation If your third‑party provider refuses programmatic rotations or rate‑limits key creation heavily, you either need a more manual flow or to negotiate better developer APIs. We hit that with one bank’s test keys; rotations had to wait for the bank’s support. For those providers, our runner marks the key as “rotation due” and requires a human to complete the step — better than nothing, but inelegant.

The takeaway I actually walked away with Automated rotations for non‑production environments buy you time and shame the shortcuts out of your workflow. But they force you to treat staging like a real environment: design workers to handle token changes, add smoke tests that exercise long‑running paths, and accept a small rollback window. Security works best when it’s boring and predictable, not heroic.

I still don’t know the “right” rotation frequency for every team. Monthly works for us; your constraints (provider APIs, worker behaviour, developer bandwidth) will determine the sweet spot. If you don’t have any rotation today, pick a cadence, script it, and get the pain of rotation into predictable ops — you’ll sleep better on Tuesdays.