API Key Security Best Practices

How-To Guide

API Key Security Best Practices

The mistakes are predictable. The fixes are too.

TL;DR

Store API keys in environment variables, never in code. Use separate keys for dev and production. Limit each key to only what it needs. Rotate critical keys every 90 days, compromised ones immediately. Monitor usage for anomalies; a sudden spike is almost always bad news. And write down your rotation process before an incident forces you to improvise it.

1. Storage Best Practices

Do This

  • Store keys in environment variables
  • Use your hosting platform's secret management
  • Keep production keys separate from development keys
  • Use a .env.example file to document required variables

Never Do This

  • Hardcode keys in source files
  • Commit .env files to git
  • Store keys in frontend/client-side code
  • Share keys via Slack, email, or other chat tools
  • Use the same key for development and production
// BAD: Hardcoded key
const stripe = new Stripe('sk_live_xxxxx');

// GOOD: Environment variable
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

// BETTER: With validation
const stripeKey = process.env.STRIPE_SECRET_KEY;
if (!stripeKey) {
  throw new Error('STRIPE_SECRET_KEY is required');
}
const stripe = new Stripe(stripeKey);

2. Key Scoping and Permissions

Give each key the minimum permissions it needs to do its job. That's it. Here's how that looks across common services:

ApproachRisk LevelRecommendation
Full access keyHighAvoid if possible
Read-only keyMediumUse when only reading data
Scoped key (specific resources)LowPreferred approach
Time-limited keyLowestUse for CI/CD, one-time tasks

Service-Specific Examples

# Stripe: Use restricted keys
# Dashboard > Developers > API keys > Create restricted key
# Only enable permissions needed (e.g., "Charges: Read" for analytics)

# AWS: Use IAM policies
# Create policies with specific actions and resources
{
  "Effect": "Allow",
  "Action": ["s3:GetObject", "s3:PutObject"],
  "Resource": "arn:aws:s3:::my-bucket/*"
}

# GitHub: Use fine-grained PATs
# Settings > Developer settings > Fine-grained tokens
# Select specific repositories and permissions

3. Key Rotation Strategy

Key TypeRotation FrequencyWhy
Payment keys (Stripe, etc.)90 daysHigh financial risk
Database credentials90 daysData access risk
Third-party API keys180 daysModerate risk
Public/anon keysAs neededLow risk if RLS enabled
Compromised keysImmediatelyActive threat

Rotation Checklist

Before Rotating

  • Generate new key in service dashboard
  • Document the new key securely
  • Prepare environment variable updates

During Rotation

  • Update production environment variables
  • Deploy or restart affected services
  • Verify new key is working
  • Revoke old key

After Rotating

  • Update local development environments
  • Notify team members
  • Update any documentation
  • Schedule next rotation

4. Monitoring and Alerting

Catching a compromised key early is the difference between a 10-minute rotation and a surprise billing spike. Watch for:

  • Usage alerts: Set thresholds for API calls (e.g., alert if OpenAI usage exceeds $100/day)
  • Geographic alerts: Flag API calls from unexpected locations
  • Rate anomalies: Sudden spikes in usage often indicate compromise
  • Failed auth attempts: Multiple failures may indicate key scanning

Service-Specific Monitoring

# OpenAI: Set usage limits
# Settings > Limits > Set monthly budget and alerts

# Stripe: Enable webhook for suspicious activity
# Dashboard > Developers > Webhooks > radar.early_fraud_warning

# AWS: CloudWatch alarms
# Set billing alarms and API call anomaly detection

5. Incident Response Plan

Don't write this plan during the incident. Write it now:

  1. Detect: How did you learn the key was compromised?
  2. Contain: Immediately rotate or revoke the key
  3. Assess: Check logs for unauthorized usage
  4. Remediate: Deploy new key, fix the exposure source
  5. Review: Document what happened and prevent recurrence

Speed Matters

Automated scanners find exposed keys within minutes. AWS keys have been used for crypto mining within 5 minutes of exposure. Have your rotation process documented so anyone on the team can execute it quickly.

6. Development vs Production

EnvironmentKey TypeExample
DevelopmentTest/sandbox keyssk_test_xxxxx
StagingTest keyssk_test_xxxxx
ProductionLive keyssk_live_xxxxx

Configure your CI/CD to use separate environment variable sets for each environment. Production keys don't belong in your dev setup, ever.

Should I encrypt API keys at rest?

If you're using environment variables in a trusted hosting platform (Vercel, Railway, etc.), they're already encrypted at rest. For self-hosted solutions, use a secrets manager like HashiCorp Vault or AWS Secrets Manager.

How do I share API keys with team members?

Use your hosting platform's team features (Vercel team settings, etc.) or a secrets manager. Don't share via Slack, email, or shared documents. If you have to share directly, use encrypted channels and rotate immediately after onboarding.

Are Supabase anon keys really safe to expose?

Supabase anon keys are designed to be public when used with Row Level Security (RLS). They're similar to Firebase's public config. The key identifies your project; RLS policies control what anyone can do with it. The service_role key is a different story: it has to stay secret.

Related guides:How to Hide API Keys · How to Rotate API Keys · How to Enable Secret Scanning

How-To Guides

API Key Security Best Practices