How to Manage LLM API Keys Without Losing Your Mind
Managing LLM API keys is fundamentally a secrets management problem with a few extra wrinkles: usage-based billing, per-application access control, and the fact that a leaked key can rack up thousands of dollars in inference costs before anyone notices. If you're searching for how to do this properly, the short answer is: never share one raw provider key across your whole stack, store keys outside your codebase, scope each key to a specific purpose, and monitor usage so anomalies surface fast.
This article covers the practical mechanics — where to store keys, how to scope and rotate them, how to catch abuse early, and when a lightweight API gateway is worth adding to the mix.
Why LLM API key management is different
Traditional API keys (payment processors, email providers) usually have hard rate limits or fixed monthly costs. LLM keys are different: usage is metered per token, costs scale with model size and context length, and a single misconfigured script or leaked key in a public repo can generate a large bill within hours. This makes three things non-negotiable:
- Isolation — each application, environment, or team should have its own key, not a shared one.
- Visibility — you need to know which key is spending what, in near real time.
- Fast revocation — if a key leaks, you need to kill it in seconds, not file a support ticket.
Where to store keys
Never hardcode keys in source files, and never commit them even to a "private" repo. The standard hierarchy:
- Environment variables for local development, loaded from a
.envfile that's git-ignored. - Secret managers (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, or your platform's built-in secrets store) for staging and production.
- CI/CD secret stores (GitHub Actions secrets, GitLab CI variables) for build and deploy pipelines — never printed to logs.
A basic local setup:
# .env (never committed)
LLM_API_KEY=sk-xxxxxxxxxxxxxxxx
import "dotenv/config";
const apiKey = process.env.LLM_API_KEY;
if (!apiKey) {
throw new Error("Missing LLM_API_KEY");
}
Add .env to .gitignore on day one, not after your first leak.
One key per application, not one key for everything
The most common mistake is provisioning a single provider key and pasting it into every service — the web app, the internal Slack bot, the batch job, the staging environment. This means:
- You can't tell which service caused a cost spike.
- Revoking the key to stop abuse breaks everything at once.
- A leak in your least-important internal tool compromises your production traffic too.
Instead, issue a distinct key per application and per environment (dev/staging/prod). Most LLM providers let you create multiple named keys under one account — use that feature even if it feels like overhead early on. The naming convention matters too: prod-web-app, staging-batch-job, internal-slack-bot is far easier to audit than key1, key2.
If your provider or gateway supports scoped keys, restrict each one to only the endpoints or models it needs. A key used purely for a support chatbot shouldn't have access to your most expensive model tier.
Rotation and expiry
Keys should be rotated on a schedule, not just after an incident:
- Rotate production keys every 60–90 days as a baseline.
- Rotate immediately after any team member with access leaves.
- Rotate immediately if a key appears in a log file, error report, or client-side bundle by mistake.
Build rotation into your deploy process rather than treating it as a manual emergency task. If your secret manager supports versioned secrets, you can push a new key, verify the new version works, then revoke the old one without downtime.
Monitoring usage and setting limits
Visibility is what turns key management from reactive to proactive. At minimum, track per-key:
- Request volume over time
- Token usage (input and output separately, since output tokens usually cost more)
- Error rates, especially 401s and 429s, which often signal a leaked or misused key
If your provider dashboard doesn't break usage down per key, or doesn't let you set hard spend caps, that's a real gap — a single runaway script or leaked key can burn through a month's budget in an afternoon.
This is where a dedicated API management layer helps. SubToAPI turns your existing Claude access into application-scoped API keys (sub_live_...) with usage metadata attached to every request, so you can see which key made which call and how many tokens it consumed, without building that instrumentation yourself. You generate keys per app from one dashboard instead of juggling raw credentials across services. See the pricing page for plan details, or check the quickstart to see how key issuance works in practice.
Handling keys across a team
Once more than one person touches your LLM integration, key management becomes an access-control problem too:
- Don't share keys over Slack or email, even "just this once."
- Use a secret manager with audit logs so you know who pulled which key and when.
- Give each team member or service account its own key where the provider supports it, rather than a single shared credential.
- Remove access immediately when someone leaves the project, not at the next sprint planning.
Team and Scale plans on SubToAPI include seat-based key management, so each developer or service gets its own scoped key under one billing account instead of everyone sharing a single Anthropic credential.
A practical checklist
- [ ] Keys live in environment variables or a secret manager, never in source
- [ ]
.envand equivalent files are git-ignored - [ ] Each application/environment has its own key
- [ ] Keys are named descriptively (
prod-web-app, notkey1) - [ ] Rotation happens on a schedule, not just after incidents
- [ ] Per-key usage and spend are visible somewhere
- [ ] Revocation takes seconds, not a support ticket
Questions
Do I need a separate key for dev and production? Yes. Mixing environments under one key means a bug in staging can consume production budget, and you lose the ability to tell which environment generated a given cost or error spike.
What's the fastest way to detect a leaked LLM API key? Watch for sudden spikes in request volume or token usage on a specific key, especially outside normal traffic patterns, and set up alerts on error rates like repeated 401s from unfamiliar sources.
Can I manage multiple LLM providers' keys the same way? Mostly yes — the storage, rotation, and per-application scoping principles apply universally. A gateway layer like SubToAPI, built specifically for Claude access, adds usage metadata and team seats on top so you're not building that tooling from scratch; see the docs for details.