# Warmup Recipes Four recipes control **how many emails the primary receives/sends per day** over the campaign duration. ## Global constraints (all recipes) | Parameter | Default | Min | Max | |-----------|---------|-----|-----| | Duration | 30 days | 14 | 45 | | Min emails/day | 1 | 1 | — | | Max emails/day | 40 | — | 50 | | Reply rate | 30% | 10% | 45% | | Volume change cap | +20% / 48h | — | Industry best practice | ## 1. Grow — Progressive (recommended) **Use when:** New domain or cold mailbox. Safest default. ### Behavior - Start at `minEmailsPerDay` (default 1) on day 1 - Increase daily toward `maxEmailsPerDay` over `durationDays` - Never increase more than 20% vs prior 48h average - After reaching max, hold flat until campaign end - Optionally continue background warmup post-campaign at 20% of max ### Algorithm (pseudocode) ``` totalGrowthDays = durationDays * 0.7 // reach max by ~70% of campaign dailyIncrement = (maxEmails - minEmails) / totalGrowthDays for day in 1..durationDays: target = minEmails + floor(dailyIncrement * min(day, totalGrowthDays)) target = min(target, maxEmails) target = cap48hIncrease(previousTargets, target, 0.20) schedule[day] = target ``` ### Example (30 days, min=1, max=40) | Day | Planned sends | |-----|---------------| | 1 | 1 | | 7 | ~8 | | 14 | ~18 | | 21 | ~30 | | 24+ | 40 | ## 2. Flat **Use when:** Mailbox already warm; maintain reputation during live outreach. ### Behavior - Constant `maxEmailsPerDay` every day - No ramp - Same reply rate and rescue rules ``` schedule[day] = maxEmailsPerDay // for all days ``` ## 3. Randomized **Use when:** Experimentation; avoid perfectly predictable patterns. ### Behavior - Daily volume random within `[minEmailsPerDay, maxEmailsPerDay]` - Weighted toward middle of range (normal distribution) - 48h spike cap still applies - Seed per campaign for reproducibility (debugging) ``` schedule[day] = randomInt(min, max, seed=campaignId+day) schedule[day] = cap48hIncrease(...) ``` ## 4. Custom **Use when:** Expert operators want per-day control. ### Behavior - User defines array: `[{ day: 1, sends: 2 }, { day: 2, sends: 5 }, ...]` - Validate: each value within [min, max], length ≤ durationDays - Missing days: hold last defined value or interpolate (configurable) - UI: spreadsheet-style editor + import CSV ## Recipe selection API (future) ```json { "recipe": "grow", "durationDays": 30, "minEmailsPerDay": 1, "maxEmailsPerDay": 40, "replyRatePercent": 30 } ``` ## Dispatcher integration 1. Load active campaigns 2. For each campaign, read `DailySchedule` for today 3. If `actualSends < plannedSends`, schedule next send slot with jitter 4. Pick satellite from `CampaignSatellite` (weighted random) 5. Primary is always receiver for satellite→primary sends; primary may send replies back ## Post-campaign | Mode | Behavior | |------|----------| | Complete | Stop sends; mark campaign `completed` | | Maintenance | Switch to Flat at 20% of max (recommended) | | Pause | Operator pause; resume later | ## UI copy (recommended labels) | Recipe | Label | Subtitle | |--------|-------|----------| | grow | Grow | Progressive ramp — recommended for new mailboxes | | flat | Flat | Steady volume — for already-warm inboxes | | randomized | Randomized | Variable daily volume — for testing | | custom | Custom | Define your own day-by-day schedule |