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:
- Generate a new key pair under a new selector.
- Publish the new public key in DNS and let it propagate.
- Switch your sending platform to sign with the new private key.
- Wait out the overlap window while old in-flight mail clears.
- 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
2026a2048-bit pair. Publish2026a._domainkey.example.comwitht=y; p=…. Leavedefaultuntouched and still signing. - Day 0 (+ propagation): Confirm
2026aresolves. Activate2026aas the signing selector. New mail now uses2026a; older mail still usesdefault. - Day 1: Inspect aggregate DMARC data and message headers; confirm
dkim=passwithheader.s=2026a. Removet=yfrom the2026arecord. - Day ~10: Overlap window elapsed. Set
defaulttop=(revoked). - Day ~17: Delete the
defaultTXT record. Rotation complete.
How to verify the new key is working
- Read message headers. Send yourself a test, then check the
Authentication-Resultsheader fordkim=passand confirmheader.s=shows the new selector andheader.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 visibleFrom: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 permanentdkim=permerror/fail. Fix: paste the record exactly as your platform provides it. - Leaving
t=yon 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
- Pick a dated selector name and generate a 2048-bit key.
- Publish the new public key (with
t=y) and let DNS propagate. - Switch signing, verify
dkim=passon the new selector, then dropt=y. - 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.