What actually happens at 102KB
Gmail measures the rendered HTML of the exact message that arrives, after every merge tag and personalization token has been filled in, not the source template and not a minified dev build. Once that crosses roughly 102KB, Gmail clips the message body at that byte and inserts "[Message clipped] View entire message," a link out to a web-hosted copy of the full email.
Everything past that cut point is still technically present in the message; it's just not what the recipient sees without clicking through. For a template that keeps its unsubscribe link, physical address, and tracking pixel in the footer, which is nearly every template, that's exactly the content that gets clipped first.
Why this is worse than a rendering glitch
- Compliance: if the unsubscribe link only exists past the clip point, the message a recipient actually sees on first render has no visible opt-out, even though the underlying HTML technically contains one.
- Analytics: an open-tracking pixel placed at the very bottom, a common default in a lot of ESP templates, gets clipped along with everything else on the heaviest sends, so the most content-dense campaigns can under-report opens for reasons that have nothing to do with whether they were actually opened.
- The List-Unsubscribe header is immune to all of this. It lives at the SMTP header level, not in the HTML body, so it survives clipping regardless of message weight. It's a real safety net, not a substitute for keeping the body lean.
The real thresholds
60KB is comfortable, no real risk. 80KB is the ceiling worth treating as a hard limit to stay under for headroom. 95KB is where the risk stops being theoretical. 102KB is Gmail's actual clip point, not a rounded-off estimate.
- Strip the redundant inline styles and repeated conditional comments a lot of builder exports (Stripo, Beefree, Mailchimp) ship by default; the same block of CSS repeated across dozens of table cells adds up fast.
- Host large images instead of embedding them as base64; an inlined image can add tens of kilobytes of raw HTML weight for something a hosted <img src> would add almost none of.
- Put the unsubscribe link and tracking pixel as early in the markup as the design allows, not dead last, so a marginal overage clips something less load-bearing first.
None of this shows up in a visual preview. A template can render perfectly in every screenshot tool and still be 20KB over the line the moment real customer data fills in every merge tag, which is exactly why size needs to be measured on the shipped output, not eyeballed from a design file.