DMARC Engine
Home/Blog/The DMARC pct tag and sampling, explained
Blog

The DMARC pct tag and sampling, explained

The DMARC pct tag samples how often your policy is applied to failing mail, pushing the remainder down one level. Here is why pct=0 is a downgrade trap, how receivers actually apply the sample, and how to ramp pct safely from p=none to a full p=reject.

6 June 2026 · 15 min read

The DMARC pct tag and sampling, explained

If you have ever opened a DMARC record and seen something like pct=25, you have met one of the most misunderstood controls in email authentication. The pct tag is a sampling dial. It tells receiving mail servers what percentage of failing messages should actually be subjected to your DMARC policy, and what percentage should be let through with a softer outcome. Used well, it is a smart way to ease a domain from monitoring towards full enforcement. Used carelessly, particularly when set to zero, it quietly turns your published p=reject into something far weaker than you think.

This article explains exactly what pct does, how mailbox providers interpret it, why pct=0 is a downgrade trap rather than a clever trick, and how to ramp the percentage safely on your way to a full p=reject. There are concrete examples throughout, and pointers to the free tools you can use to check your own record as you go.

If you want to see what your domain publishes right now before reading on, run it through the DMARC checker. The output will show the parsed pct value alongside your policy, so the rest of this guide will map directly onto your real record.

What the pct tag actually is

DMARC is defined in RFC 7489. The pct tag (short for percent) is an optional tag in your DMARC TXT record that takes an integer from 0 to 100. Its job is to limit how often the published policy is applied to messages that fail DMARC.

A failing message is one that does not pass DMARC: it fails both SPF alignment and DKIM alignment. (Alignment matters here, and it trips a lot of people up. A message can pass raw SPF or raw DKIM yet still fail DMARC because the authenticated domain does not align with the From: domain. If that distinction is new to you, the SPF checker and DKIM checker will show you what each mechanism authenticates.)

When a message fails DMARC, the receiver looks at your policy. Your policy is one of three values:

  • p=none: take no action, just report.
  • p=quarantine: treat failing mail as suspicious, usually deliver to spam or junk.
  • p=reject: refuse the message outright, typically with an SMTP rejection.

The pct tag sits on top of that policy and says: apply this policy to only this percentage of failing messages. If you omit pct, the default is pct=100, which means the policy applies to every failing message. That default is almost always what you want once you are enforcing.

So a record like this:

v=DMARC1; p=quarantine; pct=50; rua=mailto:reports@dmarcengine.com

means: of all the messages that fail DMARC for this domain, roughly half should be quarantined, and the other half should be treated as if the policy were one step softer.

The crucial detail: what happens to the unsampled portion

Here is the part most explanations skip, and it is the part that makes pct behave in ways people do not expect.

The messages that fall outside the sampled percentage are not simply passed through untouched. Instead, RFC 7489 specifies that the receiver applies the next lower policy to them. The downgrade ladder is:

  • A p=reject policy with pct below 100 means the sampled portion is rejected, and the remainder is treated as quarantine.
  • A p=quarantine policy with pct below 100 means the sampled portion is quarantined, and the remainder is treated as none.

So pct does not switch enforcement on and off cleanly. It splits your failing traffic between your stated policy and the policy one rung below it.

Take this record:

v=DMARC1; p=reject; pct=20; rua=mailto:reports@dmarcengine.com

A message that fails DMARC has, roughly, a 20 percent chance of being rejected and an 80 percent chance of being quarantined instead. None of it is delivered cleanly to the inbox, because even the unsampled portion drops to quarantine, not to none. That is a genuinely partial enforcement posture, and it can be useful.

Now compare it with a record at p=quarantine:

v=DMARC1; p=quarantine; pct=20; rua=mailto:reports@dmarcengine.com

Here a failing message has a 20 percent chance of being quarantined and an 80 percent chance of being treated as none, which means delivered. That 80 percent is real inbox delivery of unauthenticated mail. This is a much weaker stance, and it is the right kind of weak when you are early in a rollout and cannot yet afford to junk legitimate mail you have not finished authenticating.

The practical lesson: the effect of a given pct value depends entirely on which policy it modifies. pct=20 under reject is strict. pct=20 under quarantine is lenient. Always read the two tags together.

Why pct=0 is a downgrade trap, not a safe mode

This is the single most important thing to understand about pct, and it catches out a lot of people who think they are being cautious.

A common but mistaken mental model goes like this: "I will publish p=reject; pct=0 so that I get the strong policy on record, but it applies to zero percent of mail, so nothing actually gets rejected. It is reject with the brakes fully on." That reasoning feels safe. It is wrong, and it is wrong in a way that can hurt you.

Apply the downgrade rule. With pct=0, the sampled portion is zero, so 0 percent of failing mail receives your stated policy. The remaining 100 percent receives the next policy down. For p=reject, that next policy is quarantine. For p=quarantine, that next policy is none.

So:

  • p=reject; pct=0 behaves, for every failing message, as p=quarantine.
  • p=quarantine; pct=0 behaves, for every failing message, as p=none.

In other words, pct=0 silently demotes your policy by one full level. You believe you have published reject. The world treats you as quarantine. You believe you have published quarantine. The world treats you as none, which is no protection at all.

It gets worse in practice for a second reason. Receivers are inconsistent about how they read pct=0. The downgrade behaviour above is what the specification implies, and many receivers follow it. Others have historically treated pct=0 more loosely. Some reporting and analysis tools, and some external lookups, will display your domain as enforced at reject because they read the p= tag and stop there. So you end up with a record that looks fully enforced on a dashboard, behaves like a softer policy at the actual mailbox, and behaves inconsistently across providers. That is the worst of all worlds: a false sense of security with unpredictable real behaviour.

The honest summary is simple. pct=0 is not a way to stage reject. It is a way to publish reject while only ever delivering quarantine outcomes, and to confuse your own monitoring while you are at it. If your goal is to be at quarantine, then publish p=quarantine and mean it. If your goal is genuine staging, ramp pct upward from a low non-zero number, which is what the rest of this guide covers.

There is one narrow, legitimate use of pct=0 worth naming, because you may read about it elsewhere. Some operators use p=reject; pct=0 as a deliberate signal to generate failure reports and aggregate data at the reject posture without actually rejecting anything, as a final dry run. This works only if you fully understand that real-world behaviour will be quarantine, and only if your reporting tooling correctly reflects that. For almost everyone, it is safer and clearer to stay at an explicit p=quarantine with full pct while you finish your work, and then move to p=reject; pct=100. Do not reach for pct=0 as a default beginner setting. It is a sharp tool, not a safety net.

How receivers actually apply the sample

The sampling is probabilistic, per message, on the receiver's side. The receiver effectively rolls a weighted die for each failing message and decides whether that message falls into the sampled group or the remainder. It is not a perfectly even split, and it is not coordinated across providers. With pct=25 you should expect roughly a quarter of failing messages to get the stated policy over a reasonable volume, but on any given hour, or for any single sender, the proportion can wander.

Two consequences follow from this that matter for how you run a rollout.

First, low volumes are noisy. If a particular legitimate but misconfigured sender only sends you a handful of failing messages per day, pct sampling gives you a small and erratic sample. You might see no rejections one day and several the next, purely by chance. Do not read too much into short windows. Look at trends across days and across senders, which is exactly what aggregate reports give you. The DMARC report analyzer is built to turn those XML aggregate reports into a readable picture of which sources are passing, which are failing, and at what volume.

Second, pct controls enforcement, not reporting. You still receive aggregate reports (RUA) on essentially all of your failing and passing traffic regardless of the pct value, because reporting is governed by the rua tag and is independent of the sampling. So even at pct=10, your visibility into the full picture stays intact. That is what makes ramping safe: you are throttling the consequences while keeping full sight of the data. If you have not set up report collection yet, see reading your first DMARC report for what those files contain and how to interpret them.

A worked ramp from none to reject

The whole point of pct is to let you increase enforcement gradually so that, if some legitimate sender is still failing alignment, only a slice of its mail is affected at first, giving you time to notice and fix it before the policy bites everything. Here is a concrete, sane progression. Treat the timings as a guide, not a rule; the data should drive each step, not the calendar.

Start in pure monitoring. There is no pct here because at none it does nothing useful.

v=DMARC1; p=none; rua=mailto:reports@dmarcengine.com

Sit at none until your aggregate reports show that all of your legitimate mail streams (your mail platform, your marketing tool, your invoicing system, your help desk, your CRM) are passing DMARC through aligned SPF or aligned DKIM. This is the homework. Skipping it is the number one cause of self-inflicted outages. The article will enforcing DMARC break my email walks through how to read your sources and what "aligned" really requires.

When the data is clean, move to quarantine with a small sample.

v=DMARC1; p=quarantine; pct=25; rua=mailto:reports@dmarcengine.com

Now a quarter of failing mail gets quarantined and three quarters drops to none. Watch the reports for a week or two. If nothing legitimate is landing in the failing bucket, raise the sample.

v=DMARC1; p=quarantine; pct=50; rua=mailto:reports@dmarcengine.com

Then to full quarantine.

v=DMARC1; p=quarantine; pct=100; rua=mailto:reports@dmarcengine.com

Or simply drop the tag, since pct=100 is the default:

v=DMARC1; p=quarantine; rua=mailto:reports@dmarcengine.com

Hold at full quarantine until you are confident. At quarantine with no pct, every failing message is being quarantined, so any remaining misconfiguration is now visible and contained: legitimate mail that still fails will go to spam rather than the inbox, which is annoying but recoverable, not lost. Resolve anything that surfaces.

Now repeat the same ramp at the reject level.

v=DMARC1; p=reject; pct=25; rua=mailto:reports@dmarcengine.com

Remember the downgrade rule: the 75 percent that is not sampled here is treated as quarantine, not delivered. So this step is genuinely stricter than full quarantine, not looser. Increase steadily.

v=DMARC1; p=reject; pct=50; rua=mailto:reports@dmarcengine.com

And finally, arrive at the destination.

v=DMARC1; p=reject; rua=mailto:reports@dmarcengine.com

That is full enforcement. Spoofed mail using your exact domain in the From: is now rejected outright. For a deeper treatment of the whole journey and the common traps, reach p=reject without breaking email covers the operational side in detail.

How long to wait at each step

There is no universal number, because the right dwell time depends on your sending volume and your sending variety. Some practical guidance:

  • High-volume, simple setups (one mail platform, predictable traffic) can move quickly, often a few days per step, because a few days produce enough data to be confident.
  • Low-volume or highly varied setups (lots of third-party senders, monthly billing runs, seasonal campaigns) need longer. You must let a full sending cycle pass at each step. If you invoice on the first of the month, do not jump from pct=25 to pct=100 on the second; you have not yet seen your invoices flow under the new setting.
  • Always wait for a clean window, not just an elapsed window. The question is not "has a week passed" but "have I seen all of my legitimate senders pass under this setting". Calendar time is a proxy for data, and a poor one on its own.

The reason pct exists at all is to make these waits low risk. A misconfigured sender at pct=25 reject loses a quarter of its mail to rejection and three quarters to quarantine, which is bad but bounded and loud. The same sender at pct=100 reject loses everything silently to the void. Ramping buys you a margin to catch the problem while it is still small.

Subdomains, sp, and how pct interacts

A couple of related tags often appear in the same conversation, and it helps to know how they relate to pct.

The sp tag sets the policy for subdomains, separately from the p tag that governs the organisational domain. The pct tag applies to whichever policy is in force for the message's domain. If you are running a different posture on subdomains, your sampling maths needs to be done against the policy actually applied to that subdomain, not against p. For how subdomain records and policies fit together, see should I add a DMARC record on a subdomain.

It is also worth saying plainly that pct does not interact with SPF or DKIM configuration at all. It does not make a failing message pass; it only decides what happens to messages that have already failed. If your problem is that a legitimate sender fails alignment, pct is a way to soften the blow temporarily, not a fix. The fix is to align that sender, usually by adding it to your SPF record correctly (mind the ten-lookup limit, which the SPF checker will flag) or by setting up DKIM signing on the aligned domain. The case study a legitimate service is not aligned at reject is exactly this scenario.

Common mistakes with pct

A short field guide to the errors that come up most often:

  • Treating pct=0 as "reject but safe". As covered above, it silently downgrades you a level and confuses your monitoring. Do not use it as a beginner default.
  • Forgetting the default is 100. Omitting pct does not mean "no sampling, deliver everything". It means full enforcement of whatever p you set. If you publish p=reject with no pct, you are at full reject immediately.
  • Reading pct without reading p. The same number means very different things under quarantine and reject. Always evaluate the pair.
  • Ramping on the calendar, not the data. Stepping up because a week elapsed, rather than because the reports are clean, is how you reach reject with a broken sender still in the mix.
  • Leaving pct below 100 forever. A permanent pct=70 is not a finished rollout. It means roughly a third of spoofed mail still gets the softer outcome. The destination is pct=100 (or no pct) at reject. Sampling is a staging tool, not a resting place.
  • Assuming every receiver samples identically. They do not. The split is probabilistic and provider-specific. Use aggregate reports across providers to see the real aggregate behaviour rather than inferring it from one mailbox.

If you want to generate a syntactically correct record at any of these stages without hand-editing TXT strings, the DMARC generator will build the record for you and let you set p, sp, pct and your reporting addresses, then you can confirm the published result with the DMARC checker.

The practical takeaway

The pct tag is a sampling dial that limits how often your DMARC policy is applied to failing mail, and it pushes the unsampled remainder down one policy level rather than letting it through clean. That single mechanic explains everything about it: why pct=25 is strict under reject but lenient under quarantine, and why pct=0 is a downgrade trap that quietly demotes your policy while making your dashboards lie to you. Used as intended, you ramp pct upward, in steps, driven by clean aggregate-report data rather than the calendar, first through quarantine and then through reject, until you land at full enforcement with pct=100 (or the tag omitted) at p=reject.

Two habits keep this safe. Keep your reporting on the whole time, because reporting is independent of pct, so you never lose visibility as you tighten. And never confuse the staging value with the destination: sampling below 100 is a temporary scaffold, and a domain is only truly protected once it is at full reject with no sampling. To see exactly where your domain sits today, run it through the DMARC checker and turn your raw reports into a clear source-by-source view with the DMARC report analyzer.

If you would rather not run this ramp by hand, that staged progression from p=none to a full p=reject, with continuous monitoring and an alert the moment a legitimate sender starts failing, is precisely what our done-for-you DMARC service handles end to end, and you can have changes watched for you through monitoring with change alerts so nothing drifts after you reach enforcement.

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.