
What the AI crawlers actually fetched from this site in one week
SAGARIS5 min
BlogEngineering
Going up is rate-limited to one step per day. Coming down is evaluated on every tick. That asymmetry is not an oversight, it is the only correct shape.

Two pieces of code decide how fast a sending domain moves. One of them advances the ramp. One of them stops it. They run on different clocks, and the gap between those clocks is the entire subject of this article.
From the doc comment on the function that advances a warmup schedule, in the maintenance worker: advancement, slowdown and hold happen at most once per usage day, tracked via last-advanced-day metadata, so the worker advances per usage day rather than per tick. A pause or resume, by contrast, is evaluated on every call, so a degradation can stop a schedule immediately rather than waiting for the next usage day.
Read that twice. Forward motion is rate-limited by construction. The stop is not. That is deliberate, and it is the correct answer.
The committed warmup curve lives in a single configuration file, embedded into the Go mail plane and imported by the TypeScript application so both read the same numbers. For a sending domain, the daily cap steps 15, 30, 60, 90, 120, with each milestone starting seven days after the last and a hard ceiling of 150. For an individual mailbox it steps 5, 10, 20, 30, 40 with a ceiling of 50. Pool and account scopes use a separately ratified envelope of 50, 100, 200, 400 under a ceiling of 500, hardcoded in the Go engine rather than read from that file.
Five milestones a week apart puts the domain plateau on day 28. That is the month in the title, and it is worth being precise about what it buys. Not a reputation. The absence of one specific negative signal: a brand-new sending identity emitting volume it has no history to justify.
Two independent guards keep that curve honest, and the duplication is the interesting part. The ramp producer clamps every weekly increase to at most twice the prior week's cap while expanding the milestones into a day-indexed curve. Separately, the configuration loader validates the committed configuration on load and rejects a weekly series that is non-positive, decreasing, or exceeds that same 2x velocity limit, and an invalid embedded configuration panics rather than starting. So an unsafe milestone edit fails when the binary loads it, and would be clamped even if it somehow got past that. The comment on the producer version gives the reasoning: keeping the guard there makes an unsafe milestone edit safe before it ever reaches a schedule.
Look at the committed domain series against that rule. 15 to 30 is exactly 2x. 30 to 60 is exactly 2x. 60 to 90 is 1.5x, and 90 to 120 is about 1.33x. The curve leans on its own ceiling early and then deliberately flattens, which is the opposite of what an impatient operator would write.
The scheduler does not advance on the calendar. It advances on a health signal, and the classifier that reads that signal is a four-way decision:
- Quarantined or paused enforcement, a quarantined or paused health status, or a quarantine reputation tier: pause. The schedule stops. - Limited enforcement, a degraded status, or a degraded tier: slow. The applied ramp position steps one day back, toward the floor. - A watch status or tier: hold. The cap freezes where it is. - Everything else, explicitly including no signal at all, which is the normal state for a fresh sender: advance.
That last clause matters more than it looks. A brand-new domain has no reputation history, so treating silence as a reason to stall would mean nothing could ever start. Absence of evidence advances; evidence of harm does not.
The tiers underneath come from a single score-to-tier function in the measurement package: 90 and above is excellent, 75 and above good, 60 and above watch, 40 and above degraded, and anything below 40 is quarantine. And the signal reaches that score fast: the reputation fast loop carries a default target latency of 60 seconds from signal to updated score, over a one-hour hot window.
Now put the two halves side by side, which is the whole argument.
Going up: one step per usage day, at most, with each weekly milestone capped at twice the last, plus a two-hour grace window after midnight so a restart just past the date boundary cannot take the day's step on gate inputs that have not landed yet. Twenty-eight days of that to reach the domain plateau.
Coming down: a signal lands, the fast loop targets 60 seconds to move the score, a score below 40 is a quarantine tier, a quarantine tier classifies as pause, and pause is evaluated on every worker call rather than once a day. The same grace window that delays the daily step explicitly does not delay a pause or resume.
Twenty-eight days up. One classification down. Not one step down: a stop.
The instinct of most engineers meeting this design is to smooth it. If we are careful about how fast we climb, shouldn't we be equally careful about how fast we retreat? A hair-trigger pause on a noisy signal takes a healthy sender off the air.
The answer is that the two errors do not cost the same, and a control should be shaped by its asymmetric cost rather than by symmetry for its own sake.
Being one day too slow costs you one day of volume. It is annoying, it is measurable, and tomorrow is unaffected. Being one day too fast costs the sending identity, and the recovery is not one day of slowness. Inside our own machinery it is a stopped schedule, then a climb back at the same 2x-clamped weekly pace from wherever the applied ramp position was pushed down to. What the receiving side does with a damaged domain over that period is not something we can measure and is not claimed here.
There is also arithmetic underneath it. Google tells bulk senders to keep spam rates reported in Postmaster Tools below 0.30 percent, per its sender guidelines fetched 14 August 2026. A rate is a ratio, and any ratio computed over a window has a denominator. The reasoning that follows is ours and not a claim about Google's implementation: the same absolute number of complaints moves a small denominator much further than a large one, which is exactly why a young sender is the one that can be destroyed in an afternoon while a mature one is merely damaged. The period during which a domain is most fragile is precisely the period when it has sent the least. That is what a warmup ramp is actually protecting against, and it is why the ramp climbs slowest when the domain is newest.
Which gives the general rule, and it applies well beyond email. When the cost of your two failure directions differs by an order of magnitude, a symmetric control is the wrong control. Rate-limit the cheap direction. Leave the expensive one on a hair trigger.
Three details here exist because somebody hit the failure they prevent, and they are the ones most likely to be missing from a system built quickly.
The applied ramp position is not the calendar position. Once the maintenance worker is managing a schedule, admission is clamped to the worker-managed position rather than the day count since the start date. Without that clamp, a schedule held or slowed on a health signal would still let the reservation path admit volume at the cap the calendar says it should be on by now, and the hold would be advisory. Everything that decides a cap has to read the same number, or the slowest of them is decorative.
Advancing at most once per usage day is a metadata property, not a scheduling assumption. A worker ticking every few minutes and stepping the ramp on each tick would cross a 28-day curve in an afternoon, silently, because every individual step was legal. The last-advanced-day stamp makes the daily rate a property of the data rather than of how often somebody happened to run the worker.
And the hold reason is persisted alongside the position. A ramp frozen without a recorded reason is indistinguishable from a ramp that is broken, and the operator response to those two is opposite.
No placement figures, no inbox rates, no results. SAGARIS publishes no inbox-placement percentage and this article does not imply one. What is described above is committed machinery and a set of postures, verified by reading source at one pinned commit, and nothing here was executed.
The gate is closed, deliberately. Among the mail module's committed safety invariants: the outbound send flag remains closed until an explicit go-live decision, and required suppression, admission, limit, credential and egress dependencies fail closed. So the ramp described here is a ceiling that governs sending, not a description of sending that is happening.
And a ramp is a cap, which is worth stating because it is routinely misread. A cap answers how much you may send. It says nothing about how much arrives. Those are different questions with different evidence, and a vendor that lets the first stand in for the second is selling you a schedule and calling it a result.
The reason to care about any of it is the shape rather than the numbers. Somewhere in every sending system there is a piece of code that decides how fast the thing is allowed to speed up, and another that decides when it stops. If those two run on the same clock, one of them is wrong.
Thirty minutes, your own data, no setup.
SAGARIS opens fully in October 2026. Join the waitlist and we will be in touch before launch.