The average production application depends on a dozen or more API keys — payment processors, email services, cloud infrastructure, third-party APIs, database connections. Every one of those keys is a potential breach waiting to happen. API key management best practices aren't optional security hygiene; they're the difference between a locked-down system and one that hands attackers the keys on a silver platter. And as the jsonformatter.org incident proved, even your development tools can be the vector that leaks those credentials.
This guide covers the practical side of API key management — the environment variables, secret managers, rotation strategies, and detection workflows that keep your keys out of the wrong hands.
Stop Hardcoding Secrets in Source Code
This is the most common API key management mistake, and it keeps happening because it's the path of least resistance. A developer needs a Stripe key, drops it into the code, gets the feature working, and moves on. The key stays in the codebase, gets committed to Git, and now lives in the repository's history forever — even if someone deletes it later.
GitHub's own data paints a clear picture. In 2025, GitHub's secret scanning detected over 40 million leaked secrets across public repositories. That number has grown every year since they started tracking it. These aren't toy projects — they include production AWS credentials, database connection strings, and payment processing keys.
The fix starts with environment variables. Every language has a way to read them:
// Node.js
const stripeKey = process.env.STRIPE_SECRET_KEY;
# Python
import os
stripe_key = os.environ["STRIPE_SECRET_KEY"]
// Go
stripeKey := os.Getenv("STRIPE_SECRET_KEY")
For local development, use .env files loaded by dotenv (or your framework's equivalent). Add .env to your .gitignore before you create it. Provide a .env.example file with placeholder values so teammates know which variables are required without exposing real credentials.
Use a Secret Manager in Production
Environment variables work for local development, but they have real limitations in production. They're visible to any process running on the same machine. They appear in container inspection output. They can end up in crash dumps and process listings. For production workloads, a dedicated secret manager is the right call.
The major options each solve the same core problem — storing secrets encrypted at rest and delivering them to your application at runtime:
- AWS Secrets Manager — native integration with Lambda, ECS, and EC2. Supports automatic rotation for RDS database passwords. Costs $0.40/secret/month.
- HashiCorp Vault — open-source, cloud-agnostic, supports dynamic secrets (generates short-lived credentials on demand). More operational overhead, but maximum flexibility.
- Google Secret Manager / Azure Key Vault — the cloud-native options for GCP and Azure workloads respectively.
- Doppler — a developer-friendly SaaS option that syncs secrets across environments. Good for teams that want simple onboarding without managing infrastructure.
The pattern is consistent across all of them: your application authenticates to the secret manager (using instance roles, service accounts, or workload identity — never another hardcoded key), fetches the secrets it needs at startup, and holds them in memory. Secrets never touch disk, never appear in config files, and never get committed to version control.
Rotate Keys on a Schedule (And After Every Incident)
API key rotation is the practice most teams acknowledge as important and then never actually implement. The reasoning is always the same: "rotating keys means downtime" or "we'd have to update it everywhere." Both are solvable problems, and neither is an excuse for running the same production key for three years.
A practical key rotation strategy works in three phases:
- Generate the new key while keeping the old one active. Most services support multiple active keys simultaneously — AWS IAM, Stripe, and Twilio all allow this.
- Deploy the new key to your application. If you're using a secret manager, update the secret value and restart or redeploy the service. Zero-downtime deployments make this seamless.
- Revoke the old key after confirming the new one works. Monitor your error rates for 15-30 minutes after the switch, then deactivate the previous key.
Recommended rotation frequency depends on the key's blast radius. Payment processing keys (Stripe, Braintree) and cloud infrastructure keys (AWS, GCP) should rotate every 90 days at minimum. Internal service-to-service keys can follow a longer cycle if they're scoped tightly. But any key should rotate immediately after a team member leaves, a security incident occurs, or you suspect exposure through a tool like an online JSON formatter or code-sharing platform.
Detect Leaked Keys Before Attackers Do
Prevention is the first line of defense, but detection is the safety net. Keys will leak — through accidental commits, log files, error messages, or third-party tools. The question is whether you find them first.
Set up these detection layers:
- Git pre-commit hooks. Tools like gitleaks, truffleHog, and detect-secrets scan staged changes for patterns matching API keys, tokens, and credentials before they ever reach the repository. This is your cheapest and most effective defense.
- CI/CD pipeline scanning. Run the same secret-detection tools as a CI step. If a secret makes it past the pre-commit hook (maybe a developer skipped hooks with
--no-verify), the pipeline catches it before it merges. - GitHub secret scanning. If you're on GitHub, enable push protection. GitHub blocks pushes that contain recognized secret patterns from over 200 service providers. It's free for public repos and included in GitHub Advanced Security for private repos.
- Runtime monitoring. Cloud providers offer tools to detect anomalous key usage — AWS CloudTrail anomaly detection, GCP's Security Command Center, and Stripe's webhook notifications for unusual activity.
Here's a quick gitleaks setup for any project:
# Install gitleaks
brew install gitleaks # macOS
# or download from https://github.com/gitleaks/gitleaks
# Scan your entire repo history
gitleaks detect --source . -v
# Add as a pre-commit hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks:
- id: gitleaks
Scope Keys to Minimum Required Permissions
A leaked key with full admin access is catastrophic. A leaked key that can only read a single S3 bucket is a contained incident. The principle of least privilege applies directly to API key management, and most services support granular permission scoping.
Practical scoping strategies:
- Create separate keys for each environment. Development, staging, and production should never share credentials. A leaked dev key shouldn't compromise production data.
- Use read-only keys where writes aren't needed. If a service only reads from an API, its key shouldn't have write permissions.
- Restrict by IP or network. Many APIs let you restrict key usage to specific IP ranges. Your production servers have known IPs — lock the key to those addresses.
- Set usage quotas. Rate limits on API keys can cap the damage from a compromised credential. If your key is limited to 100 requests/minute, an attacker can't run up a $50,000 cloud bill overnight.
Audit Your Developer Tools
Your API key management strategy is only as strong as the tools touching your keys. The jsonformatter.org breach exposed 80,000+ credentials not because developers had weak key management — but because they pasted config files containing secrets into an online tool that logged everything server-side.
Before you paste any data containing secrets into an online tool, verify that it processes data client-side. Open your browser's Network tab, paste test data, and confirm zero outbound requests. Better yet, use tools that are architecturally incapable of seeing your data. PinusX's JSON Formatter and JWT Decoder run entirely in your browser — your secrets never leave your machine.
The Practical Checklist
Pin this to your team's wiki:
- No secrets in source code. Use environment variables locally, a secret manager in production.
.envis in.gitignore. Verify this today. Right now.- Pre-commit hooks scan for secrets. Install gitleaks or truffleHog on every developer's machine.
- Keys rotate every 90 days. Put it on the team calendar. Automate it if your secret manager supports rotation.
- Every key has minimum permissions. Audit existing keys and downscope anything that's over-privileged.
- Leaked keys are revoked within the hour. Have a documented incident response process for credential exposure.
- Online developer tools are vetted. Only use client-side tools for data that might contain secrets.
API key management best practices aren't complicated. They don't require expensive tooling or dedicated security teams. They require consistency — doing the boring, correct thing every time you create, store, or use a credential. The teams that get this right don't make headlines. The teams that don't end up in breach notifications.