In 2026, best practice is risk-based rotation: rotate database passwords every 30-90 days, API keys every 60 days, and user passwords only after confirmed breaches or during yearly audits – not on a fixed calendar schedule. Use dynamic secrets (HashiCorp Vault) for database credentials and automate API key rotation with expiration monitoring. This guide provides the complete rotation schedule by credential type, automation scripts, and monitoring configurations.

Why Rotation Still Matters

Even with the best password managers generating unique, complex credentials, rotation provides defense in depth. If a service experiences a breach, rotated credentials limit the window of exposure. High-privilege accounts, API keys, and service tokens particularly benefit from regular rotation schedules.

The key is applying rotation intelligently rather than mechanically. Not every credential needs the same treatment. A developer team’s production database credentials warrant different handling than a personal email account.

Risk-Based Rotation Schedules

The 2026 approach categorizes credentials by sensitivity and exposure risk:

Credential Type Rotation Frequency Trigger Conditions
Database passwords Every 30-90 days After any staff change, on incident
API keys Every 60 days On deployment, after suspicious activity
Service accounts Every 90 days After team member departure
User passwords As needed After confirmed breaches, yearly audits
SSH keys Every 180 days On key compromise or离职

This table represents starting points. Adjust based on your threat model. Financial services and healthcare often face stricter regulatory requirements.

Automating Rotation with Password Managers

Modern password managers include rotation features that integrate directly with services. Here’s how to set up automated rotation:

Bitwarden CLI Rotation

# Generate and update a password for a specific entry
bw get item "Production Server" | jq '.id'
# Store the item ID
ITEM_ID="your-item-id-here"

# Generate new password and update
NEW_PASSWORD=$(bw generate -uln --length 24)
bw edit item $ITEM_ID --password "$NEW_PASSWORD"

# Sync to ensure vault is updated
bw sync

You can wrap this in a cron job or CI pipeline for automated rotation:

# Add to crontab for weekly rotation
0 2 * * 0 /usr/local/bin/rotate-secrets.sh >> /var/log/rotation.log 2>&1

HashiCorp Vault for Dynamic Secrets

For applications with database credentials, Vault’s dynamic secrets eliminate manual rotation entirely:

# Configure database secrets engine
vault secrets enable -path=my-database database

# Configure connection
vault write my-database/config/my-postgres \
    plugin_name=postgresql-database-plugin \
    connection_url="postgresql://{{username}}:{{password}}@localhost:5432/mydb" \
    allowed_roles="my-role"

# Create role with automatic rotation
vault write my-database/roles/my-role \
    db_name=my-postgres \
    creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';" \
    default_ttl="1h" \
    max_ttl="24h"

Applications request credentials from Vault, which generates unique, short-lived credentials automatically. When the TTL expires, Vault revokes and rotates the credentials without any manual intervention.

// Example: Fetching dynamic credentials in Go
import vault "github.com/hashicorp/vault/api"

func getDatabaseCredentials() (*vault.Secret, error) {
    config := vault.DefaultConfig()
    client, _ := vault.NewClient(config)
    
    secret, err := client.Logical().Read("my-database/creds/my-role")
    if err != nil {
        return nil, err
    }
    return secret, nil
}

SSH Key Rotation

SSH keys warrant special attention for developers. Ed25519 keys offer better security than RSA while maintaining performance:

# Generate new Ed25519 key
ssh-keygen -t ed25519 -C "work-laptop-2026"

# Set key comment with date for tracking
# Output public key to add to servers

# Rotate keys on remote servers
for server in server1 server2 server3; do
    ssh $server "echo '$(cat ~/.ssh/id_ed25519.pub)' >> ~/.ssh/authorized_keys"
done

For teams using a central CA, consider implementing SSH certificates instead of managing authorized_keys directly. This approach provides instant revocation and eliminates the need to update multiple servers when rotating keys.

API Key Management

API keys often receive less attention than user credentials but can expose significant attack surface. Implement these practices:

# Example: Rotating API keys in a Flask application
import os
import time
from datetime import datetime, timedelta

class APIKeyManager:
    def __init__(self, db):
        self.db = db
    
    def rotate_key(self, user_id, key_id):
        # Invalidate old key
        self.db.execute(
            "UPDATE api_keys SET active = FALSE WHERE id = ?",
            (key_id,)
        )
        
        # Generate new key
        new_key = os.urandom(32).hex()
        expires_at = datetime.utcnow() + timedelta(days=90)
        
        self.db.execute(
            """INSERT INTO api_keys 
               (user_id, key_hash, created_at, expires_at, active)
               VALUES (?, ?, ?, ?, TRUE)""",
            (user_id, hash(new_key), datetime.utcnow(), expires_at)
        )
        
        return new_key
    
    def enforce_rotation(self, max_age_days=90):
        cutoff = datetime.utcnow() - timedelta(days=max_age_days)
        return self.db.execute(
            "SELECT user_id, key_id FROM api_keys WHERE created_at < ? AND active = TRUE",
            (cutoff,)
        )

Store API keys in environment variables or secrets management, never in source code. Tools like Doppler or Infisical integrate with your development workflow to provide secret rotation without code changes.

Monitoring and Alerts

Rotation policies only work if you can verify compliance. Set up monitoring:

# Example: Prometheus alert for expiring credentials
groups:
- name: credential-expiry
  interval: 24h
  rules:
  - alert: APICredentialExpiringSoon
    expr: credential_expiry_timestamp - time() < 604800  # 7 days
    for: 1h
    labels:
      severity: warning
    annotations:
      summary: "API credential expiring in less than 7 days"
      
  - alert: SSHKeyNotRotated
    expr: time() - ssh_key_last_rotated > 15552000  # 180 days
    for: 24h
    labels:
      severity: critical

Service Account Rotation

Service accounts often cause the biggest headaches because they lack human owners. Implement a registry:

{
  "service_accounts": [
    {
      "name": "ci-deployment",
      "environment": "production",
      "owner": "devops-team",
      "last_rotated": "2026-02-15",
      "rotation_interval_days": 30,
      "credential_type": "service_principal"
    },
    {
      "name": "backup-scheduler",
      "environment": "staging",
      "owner": "infrastructure",
      "last_rotated": "2026-03-01",
      "rotation_interval_days": 60,
      "credential_type": "api_token"
    }
  ]
}

Run periodic audits against this registry to identify neglected credentials.

Implementation Checklist

  1. Audit existing credentials - Know what you have before establishing rotation
  2. Categorize by risk - Not all credentials need the same schedule
  3. Implement automation - Manual rotation introduces human error
  4. Document exceptions - Some systems cannot rotate; document why and mitigate
  5. Test recovery procedures - Verify you can access systems after rotation
  6. Monitor compliance - Alert on credentials approaching rotation deadlines
  7. Review quarterly - Adjust schedules based on incident data and team feedback

Conclusion

Password rotation in 2026 focuses on automation, risk-based scheduling, and continuous monitoring rather than calendar-based mandates. Implement dynamic secrets where possible, automate API key rotation, and maintain clear ownership of all credentials. The goal isn’t rotation for its own sake—it’s limiting the blast radius when credentials inevitably leak.

Start with your highest-privilege credentials, automate what you can, and build from there. Small, consistent improvements beat comprehensive policies that nobody follows.


Built by theluckystrike — More at zovo.one