DKIM key rotation is one of those operational tasks that organizations delay far longer than they should, then rush through badly when they finally do it. A poorly executed DKIM rotation — removing the old DNS record too early, failing to confirm the new key is actually signing outbound mail, or rotating without a drain period — causes authentication failures that DMARC treats as failures, producing 550 rejection errors at Gmail and Microsoft. This guide provides a zero-downtime rotation procedure with specific steps for OpenDKIM (self-hosted), Google Workspace, and Microsoft 365, plus the selector naming convention and monitoring process that makes rotations routine rather than crises.

6 months
M3AAWG recommended DKIM key rotation interval
2048-bit
minimum RSA key length — 1024-bit deprecated by all major ISPs
14 days
TTL overlap period — keep old selector active after rotation
Ed25519
modern alternative to RSA — 68-byte key vs 392-byte; 2x faster
Key typeKey lengthDNS record sizeISP supportRecommended?
RSA-10241024-bit~200 bytesDeprecated — rejected by GmailNo
RSA-20482048-bit~392 bytesSupported by all ISPsYes — current standard
RSA-40964096-bit~780 bytes (may exceed DNS TXT limit)Supported but size issuesOnly if TXT size allows
Ed25519256-bit~68 bytesGmail, Yahoo, most modern; not OutlookDual-sign RSA+Ed25519

Why DKIM Key Rotation Matters

Cryptographic exposure risk

DKIM private keys are long-lived secrets used to sign every outbound email your domain sends. The longer a key is in service, the more signing operations have occurred with it and the more exposure the private key material has experienced. A key that's been active for three years has been:

  • Stored on multiple mail servers over that period (each a potential compromise vector)
  • Potentially accessed by employees who have since left the organization
  • In use through operating system upgrades, server migrations, and vendor changes where proper key management may not have been followed

The 1024-bit to 2048-bit migration

Many organizations that set up DKIM more than three years ago are still using 1024-bit RSA keys. In 2025, this is a security concern that has become an operational concern: NIST officially deprecated RSA-1024 in 2024, and an increasing number of receiving mail servers log a warning or apply penalty scoring to mail signed with 1024-bit keys.

You can identify your current key length:

# Query your DKIM DNS record
dig TXT mail._domainkey.yourdomain.com +short

# Count the characters in the p= value
# ~200 characters = 1024-bit key (insufficient)
# ~350 characters = 2048-bit key (current standard)
# ~700 characters = 4096-bit (too large for some DNS providers — don't use)

A DKIM key rotation that also upgrades from 1024-bit to 2048-bit is doubly valuable and should be prioritised immediately if your current keys are 1024-bit.

Rotation frequency: the M3AAWG recommendation

The Messaging, Malware and Mobile Anti-Abuse Working Group (M3AAWG) recommends rotating DKIM keys at least every six months, with quarterly rotation preferred for high-volume senders and organisations with complex email ecosystems. MxToolbox's published best practices align: six-month minimum, more frequent for sensitive or high-volume operations.

In practice, most organisations rotate annually or less. Starting at six months and optimising from there is more achievable than a quarterly schedule you'll miss. A rotation plan that's actually followed beats an ideal one that never ships.

Selector Naming Convention

The selector is the identifier in the DKIM-Signature header that tells receiving servers which DNS record to look up for the public key. For rotation to work cleanly, each rotation must use a new selector name — you can't rotate the key under the same selector without a blackout period.

DKIM-Signature header — RSA-2048 correctly configured
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  d=yourcompany.com;           ← signing domain (must match From:)
  s=2025q1;                    ← selector name (matches DNS TXT record)
  h=from:to:subject:date:message-id:content-type;
  bh=ABC123xyz/hash==;         ← body hash
  b=MEQCIAbc/signature...;     ← actual signature

# DNS record the recipient checks:
# 2025q1._domainkey.yourcompany.com IN TXT
# "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg..."

# Rotation: publish selector 2025q3 BEFORE switching from 2025q1.
# Run both selectors simultaneously for 14 days during drain period.
DKIM failure — selector not found (key removed too early)
Authentication-Results: mx.google.com;
  dkim=fail (no key for signature) header.i=@yourcompany.com
       header.s=2024q4;

# Cause: key 2024q4 was deleted from DNS before all in-flight
# messages were delivered. Any message signed with the old key
# that arrives after deletion will fail DKIM verification.
# Fix: always maintain old selector for 14+ days after rotation.

Best practice selector naming formats:

  • Date-based quarterly: 2026q1, 2026q2, 2026q3, 2026q4
  • Date-based monthly: 2026m01, 2026m04
  • ISO date: 20260401, 20261001

Date-based selectors are strongly preferred over generic names (mail, default, key1). When you look at a DKIM-Signature header showing s=2026q1, you immediately know this key was generated in Q1 2026 without consulting any documentation. When troubleshooting a DMARC failure, you can instantly see which rotation period the signing key belongs to. When auditing email infrastructure, you can confirm at a glance that every domain is using current keys.

Zero-Downtime Rotation Procedure (General)

The fundamental principle of zero-downtime rotation: publish the new key before decommissioning the old one, and maintain both simultaneously for a drain period.

Timeline:
Day -7:  Lower DNS TTL on old DKIM record from 3600s to 300s
Day 0:   Generate new 2048-bit key pair
Day 0:   Publish new public key to DNS under new selector
Day 1:   Verify new DNS record is resolving globally
Day 2:   Update mail server/service configuration to sign with new selector
Day 2:   Send test emails; verify new selector in DKIM-Signature header
Day 2:   Verify dkim=pass in Authentication-Results headers
Day 3-7: Monitor — both old and new selectors active in DNS
Day 7:   Monitor DMARC aggregate reports — confirm zero failures from new selector
Day 14:  (Drain period complete) — remove old selector DNS record
         (Messages signed with old key that were queued/delayed have cleared)

Key steps in detail

Lower TTL early: Reducing the DNS TTL from 3600 seconds to 300 seconds seven days before rotation means any cached DNS responses expire within 5 minutes after you publish the new record, rather than within an hour. This dramatically reduces the window where recipients might be using a stale cache.

Generate the new key (OpenDKIM):

# Create directory for new key generation
DOMAIN="yourdomain.com"
SELECTOR="2026q2"

sudo mkdir -p /etc/opendkim/keys/${DOMAIN}/${SELECTOR}
sudo opendkim-genkey \
  --directory=/etc/opendkim/keys/${DOMAIN}/${SELECTOR} \
  --domain=${DOMAIN} \
  --selector=${SELECTOR} \
  --bits=2048

# View the DNS record to publish
cat /etc/opendkim/keys/${DOMAIN}/${SELECTOR}/${SELECTOR}.txt

Publish new DNS record: Create a TXT record at 2026q2._domainkey.yourdomain.com with the public key value from the .txt file. Do NOT remove the old record yet.

Verify propagation:

# Check new key is resolving
dig TXT 2026q2._domainkey.yourdomain.com +short

# Test from multiple locations using an online DNS propagation checker
# Confirm p= value is present and correct

Update OpenDKIM configuration:

# Update KeyTable — add new entry
echo "${SELECTOR}._domainkey.${DOMAIN}  ${DOMAIN}:${SELECTOR}:/etc/opendkim/keys/${DOMAIN}/${SELECTOR}/${SELECTOR}.private" \
  | sudo tee -a /etc/opendkim/KeyTable

# Update SigningTable — change domain to use new key
sudo sed -i "s/[a-z0-9]*\._domainkey\.${DOMAIN}/${SELECTOR}._domainkey.${DOMAIN}/" \
  /etc/opendkim/SigningTable

# Reload OpenDKIM
sudo systemctl reload opendkim

Verify signing is working: Send a test email to any Gmail address you control. View Show Original. Confirm:

# In Gmail's "Show Original" headers:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=yourdomain.com;
  s=2026q2; ...   <-- new selector is showing

Authentication-Results: mx.google.com;
  dkim=pass header.i=@yourdomain.com header.s=2026q2 ...  <-- pass with new selector

Microsoft 365 DKIM Rotation

Microsoft 365 handles DKIM via CNAME records that delegate signing to Microsoft's infrastructure. The rotation process is managed through the Microsoft 365 Defender portal.

# PowerShell: Check current DKIM configuration
Connect-ExchangeOnline
Get-DkimSigningConfig -Identity yourdomain.com | Select-Object Enabled, Selector1KeySize, Selector2KeySize

# Initiate key rotation
Rotate-DkimSigningConfig -KeySize 2048 -Identity yourdomain.com

Important Microsoft 365 specifics:

  • Microsoft uses two selectors (selector1 and selector2) and alternates between them on each rotation
  • Rotation does not happen instantaneously — allow 24–48 hours for the new key to take effect
  • Microsoft introduced a new CNAME format in May 2025; check current documentation before rotation if your CNAME records are more than 6 months old
  • The old selector remains active during transition — no blackout period with Microsoft's implementation

Google Workspace DKIM Rotation

Google Workspace DKIM rotation is more manual and has a brief gap risk:

  1. Go to Google Admin Console → Apps → Google Workspace → Gmail → Authenticate email
  2. Select your domain and click "Generate new record"
  3. Choose 2048-bit key length and a new selector prefix (e.g., google2026q2)
  4. Publish the generated TXT record to your DNS before clicking "Start Authentication"
  5. Wait for DNS propagation (up to 24 hours, but typically within an hour)
  6. Click "Start Authentication" in Google Admin Console

Google Workspace limitation: Google only supports one active DKIM key per domain in their system. When you generate a new key and start authentication, the old key stops signing. This creates a brief gap between when the old key stops signing and when the new key's DNS record is universally propagated. Mitigate by lowering TTL beforehand and publishing the new DNS record at least 24 hours before clicking "Start Authentication".

Drain Period and Old Key Removal

Email messages are not always delivered immediately. A message submitted to your mail server may sit in delivery queue for up to 5 days if the destination is temporarily unavailable. That queued message was signed with the old DKIM key. If you remove the old key's DNS record before that message delivers, the receiving server's DKIM verification will fail.

Standard drain period: 14 days minimum after switching all signing to the new key before removing the old DNS record. For transactional email systems where queued messages rarely age beyond 24 hours, 7 days is sufficient. For marketing email where campaigns may be sent in batches over multiple days, 14–21 days is safer.

# Remove old key after drain period
# 1. Delete the old KeyTable entry in OpenDKIM (do NOT delete the private key file yet)
# 2. Remove old DNS TXT record from your DNS provider
# 3. Set TTL back to 3600s on the new record

# Verify old record is gone
dig TXT old-selector._domainkey.yourdomain.com +short
# Should return empty result after propagation

Rotation Monitoring

After rotation, DMARC aggregate reports provide the authoritative confirmation that everything is working. Check your reports from Gmail, Microsoft, and Yahoo for the 7 days following rotation:

  • All legitimate sending sources should show dkim=pass in the policy_evaluated section
  • The auth_results section should show your new selector name in the s= field
  • Zero records should show dkim=fail for sources that are yours

If DMARC reports show unexpected DKIM failures after rotation, the most common causes are:

  1. A sending system (ESP, CRM, helpdesk) that was not updated to use the new selector — identify the source IP from the report and update that system's DKIM configuration
  2. DNS propagation still incomplete — check from multiple DNS resolvers before concluding it's a configuration issue
  3. Private key file permissions or path error in the updated OpenDKIM configuration — check mail.log for opendkim signing errors