DMARC Engine
Home/Knowledge base/How do I rotate a DKIM key safely?
Knowledge base

How do I rotate a DKIM key safely?

Rotate a DKIM key with zero downtime: publish the new selector first, switch signing, verify, then revoke the old key with an empty p=. Step-by-step with a worked example.

24 June 2026 · DMARC Engine · 7 min read

Rotating a DKIM key means replacing the cryptographic key your mail platform uses to sign outbound mail. Done correctly it is invisible to recipients and causes zero failed authentication; done in the wrong order it can break DKIM for every message in flight. The golden rule is publish the new public key before you start signing with the new private key, and keep the old key published until no mail is still signed with it. This guide walks through the safe sequence, a worked example, how to verify, and the mistakes that trip people up.

The short answer

Always overlap. A DKIM key is a pair: a private key your sender uses to sign, and a matching public key you publish in DNS at selector._domainkey.yourdomain.com. Because mail can sit in queues and relays for hours, a receiver may validate a signature long after you sent the message. So the safe order is:

  1. Generate a new key pair under a new selector.
  2. Publish the new public key in DNS and let it propagate.
  3. Switch your sending platform to sign with the new private key.
  4. Wait out the overlap window while old in-flight mail clears.
  5. Revoke the old key by emptying its public-key value (p=), then remove the old record.

Never reuse a selector for a new key, and never delete the old record the moment you switch. Both shortcuts cause dkim=fail on mail signed with a key that no longer resolves.

Why rotate at all

  • Key hygiene and compromise. If a private key is exposed, on a decommissioned server, in a leaked backup, or in a former employee's access, an attacker can forge signed mail from your domain. Rotation invalidates the leaked key.
  • Upgrading key strength. Older setups used 1024-bit RSA keys. The modern baseline is 2048-bit RSA, and rotation is how you move up. Note that a 2048-bit public key is too long for a single 255-character DNS string and must be split into multiple quoted chunks within one TXT record, your DNS provider usually handles this for you.
  • Scheduled rotation policy. Many security and compliance frameworks expect periodic rotation (for example, quarterly or annually). The exact cadence is your call; the mechanics below are identical regardless of how often you do it.
  • Changing providers or selectors. Moving senders, or splitting traffic across platforms, is effectively a rotation and follows the same overlap pattern. See authenticating mail from multiple senders if more than one platform signs your domain.

The selector is what makes safe rotation possible

Every DKIM signature header carries two key facts: the domain (d=) and the selector (s=). The receiver fetches the public key from s._domainkey.d. Because the selector is part of the lookup, you can have two live keys at once under different selectors, the old mail validates against the old selector, the new mail against the new selector. This is the entire basis of zero-downtime rotation, so the first rule is: a new key gets a new selector. A common convention is to encode the date, for example s2026a, 2026q3, or mar2026.

Step-by-step rotation

1. Generate the new key pair under a fresh selector

In your mail platform's DKIM settings, create a new signing key. Most platforms (Google Workspace, Microsoft 365, and most ESPs) generate the key for you and show you the DNS record to publish; you never touch the private key directly. If you self-host (for example OpenDKIM), generate a 2048-bit pair and pick a new selector name:

opendkim-genkey -b 2048 -s 2026a -d example.com

This produces the private key 2026a.private (kept on the signer) and 2026a.txt (the public record to publish).

2. Publish the new public key in DNS

Add a TXT record at the new selector host:

2026a._domainkey.example.com.  IN TXT (
  "v=DKIM1; k=rsa; "
  "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA…long base64…IDAQAB" )

The p= value is the public key. Leave your existing selector and key exactly as they are, both records now coexist.

Optional but recommended: include the testing flag t=y on the new record initially. t=y tells receivers you are testing and that they should not treat unsigned or DKIM-failing mail differently because of this key, it is a safety net while you confirm signing works. You will remove t=y once verified:

"v=DKIM1; k=rsa; t=y; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A…IDAQAB"

3. Wait for DNS propagation

Do not switch signing until the new record resolves everywhere. TXT records can take minutes to hours depending on the TTL you set and caching upstream, see how long DNS changes take. Setting a low TTL (300 seconds) before rotation day shortens this wait. Verify the record is live with a public lookup or the DKIM checker before proceeding.

4. Switch signing to the new key

Once the new public key resolves, change your sending platform to sign with the new selector. On hosted platforms this is usually a single "activate" or "set as primary" action. From this moment, fresh mail carries s=2026a and validates against the new record.

5. Remove the testing flag

After you confirm that real outbound mail is passing DKIM with the new selector (next section), edit the new TXT record to drop t=y. Leaving t=y in place permanently weakens the signal you send to receivers, so treat it strictly as a temporary testing aid.

6. Hold the overlap window, then revoke the old key

Keep the old selector published long enough for any mail signed with it to be delivered and validated. Because queued or deferred mail can linger, a conservative overlap is several days, many teams wait a week or two. Rotating faster than your slowest realistic delivery delay is the single most common cause of breakage.

When the window has passed, revoke the old key by setting its public-key value to empty:

old._domainkey.example.com.  IN TXT  "v=DKIM1; k=rsa; p="

An empty p= is the RFC 6376 way of saying "this key is revoked." It is cleaner than deleting the record outright, because a receiver that still sees an old signature gets an explicit revocation rather than a missing-record ambiguity. After a further short period you can delete the old TXT record entirely.

A worked example

Say your live selector is default and you are upgrading to 2048-bit under 2026a:

  • Day 0: Generate the 2026a 2048-bit pair. Publish 2026a._domainkey.example.com with t=y; p=…. Leave default untouched and still signing.
  • Day 0 (+ propagation): Confirm 2026a resolves. Activate 2026a as the signing selector. New mail now uses 2026a; older mail still uses default.
  • Day 1: Inspect aggregate DMARC data and message headers; confirm dkim=pass with header.s=2026a. Remove t=y from the 2026a record.
  • Day ~10: Overlap window elapsed. Set default to p= (revoked).
  • Day ~17: Delete the default TXT record. Rotation complete.

How to verify the new key is working

  • Read message headers. Send yourself a test, then check the Authentication-Results header for dkim=pass and confirm header.s= shows the new selector and header.d= your domain.
  • Check DMARC aggregate reports. Your RUA feed will show DKIM results per source. Look for the new selector passing across your real sending sources, not just a single test, before you revoke anything. See how to read a DMARC aggregate report.
  • Lookup the public record. Use the DKIM checker to confirm both records resolve as expected during overlap, and that the old one shows revoked (p=) afterwards.
  • Confirm alignment. DKIM only helps DMARC when the d= domain aligns with the visible From: domain. Rotation does not change alignment, but it is worth a glance if you also changed the signing domain. See check DMARC is working.

Common problems and how to avoid them

  • Revoking too early. The classic failure: you switch and immediately delete the old record, then mail still in a recipient's queue fails DKIM. Fix: always hold the overlap window.
  • Reusing the same selector. Overwriting the existing selector with a new p= value means in-flight mail signed with the old private key now fails against the new public key. Fix: every new key gets a new selector.
  • High TTL on the new record. If you set the new selector with a long TTL and got the value wrong, the bad value caches everywhere. Fix: lower TTLs before rotation, verify, then raise them.
  • Truncated 2048-bit record. A 2048-bit p= exceeds 255 characters and must be published as multiple quoted strings in one TXT record. A truncated value yields a permanent dkim=permerror/fail. Fix: paste the record exactly as your platform provides it.
  • Leaving t=y on forever. Testing mode is meant to be temporary. Fix: remove it once verified.
  • Forgetting a second sender. If two platforms sign for your domain, rotating one does not touch the other, but make sure both are covered by DMARC.

How DMARC Engine helps

Hosted DKIM with DMARC Engine manages the selector lifecycle for you: it generates 2048-bit keys, publishes the new selector through delegated DNS, watches your aggregate reports to confirm the new key is passing across real sending sources, and only then prompts you to revoke the old key, with the empty p= written automatically. That removes the two riskiest manual judgements: knowing when it is safe to switch, and knowing when it is safe to revoke.

Next steps

  1. Pick a dated selector name and generate a 2048-bit key.
  2. Publish the new public key (with t=y) and let DNS propagate.
  3. Switch signing, verify dkim=pass on the new selector, then drop t=y.
  4. Hold the overlap window, revoke the old key with an empty p=, and delete it later.

Run the DKIM checker before and after each step, and watch your DMARC reports so the cutover stays invisible to your recipients.

Share

See where your domain stands today

Run a free DMARC scan, then let us take you to enforced p=reject with no email outage.