# Primary & Satellite Topology ## Core principle **Primaries** are the mailboxes whose reputation matters for cold outreach. **Satellites** exist only to generate realistic, controlled engagement with primaries. ``` ┌─────────────────┐ │ Primary │ │ hello@fillcare │ └────────┬────────┘ │ ┌───────────────────┼───────────────────┐ │ │ │ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │Satellite│ │Satellite│ │Satellite│ │ Gmail 1 │ │ Yahoo │ │ Live │ └─────────┘ └─────────┘ └─────────┘ ``` ## Traffic rules | Direction | Allowed | Notes | |-----------|---------|-------| | Satellite → Primary | Yes | Main warmup send | | Primary → Satellite | Yes | Reply to satellite (completes thread) | | Satellite → Satellite | No | Wastes quota; looks unnatural | | Primary → Primary | No | Never warm primaries against each other | | Satellite → unrelated external | No | Only campaign-assigned primaries | ## Multi-primary support One operator can run **N campaigns** concurrently: ``` Campaign A: primary=hello@fillcareapp.com ← satellites [gmail1, yahoo1, live1] Campaign B: primary=sales@otherdomain.com ← satellites [gmail2, yahoo2] ``` Satellites may be **shared** across campaigns only if explicitly enabled (default: dedicated per primary to avoid cross-brand leakage). ## FillCare example setup | Mailbox | Role | Provider | |---------|------|----------| | hello@fillcareapp.com | Primary | Google Workspace | | personal@gmail.com | Satellite | Gmail | | personal@yahoo.com | Satellite | Yahoo | | personal@live.com | Satellite | Outlook | | (+ 1–2 more) | Satellite | Mixed | ### Minimum viable pool - 1 primary + **2 satellites** (technical minimum) - Recommended: 1 primary + **4–6 satellites** for natural variety and reply distribution ## Satellite lifecycle ```mermaid stateDiagram-v2 [*] --> Unassigned: Add mailbox Unassigned --> Active: Assign to campaign Active --> Paused: Operator pause Paused --> Active: Resume Active --> Error: Auth/IMAP failure Error --> Active: Fix + test Active --> Unassigned: Remove from campaign ``` ## Add / remove operations ### Add satellite 1. `POST /mailboxes` with `role: satellite` 2. Test SMTP/IMAP 3. `POST /campaigns/:id/satellites` to assign ### Remove satellite 1. `DELETE /campaigns/:id/satellites/:mailboxId` — stops new sends 2. In-flight threads complete or timeout 3. Optional: `DELETE /mailboxes/:id` if fully removed ### Add primary 1. `POST /mailboxes` with `role: primary` 2. `POST /campaigns` with recipe + bounds 3. Assign satellites 4. Start campaign (`status: active`) ## Peer network (phase 3 — optional) When enabled, additional engagement from vetted peer mailboxes: | Aspect | Own satellites | Peer network | |--------|----------------|--------------| | Control | Full | Limited | | ESP risk | Lower | Higher (pool quality) | | Cost | User supplies accounts | Platform fee | | Detection | User responsible | Platform must maintain pool health | **Recommendation:** Ship own-satellite-only first. Peer network requires bounce monitoring, DNS validation, and pool rotation — significant ops burden. ## Dispatcher pairing (target logic) ``` for each campaign where status=active: if today.sends < schedule.plannedSends: satellite = pickWeighted(campaign.satellites) primary = campaign.primaryMailbox queueSend(from=satellite, to=primary) ``` Reply path (rescuer): ``` if shouldReply(campaign.replyRatePercent): reply(from=primary, to=satellite, inReplyTo=original) ```