| Mail Client | Owns client protocol, request identity, retry, and resume behavior. In this design it participates in: Authenticate submission and durably store the immutable MIME body. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents the external caller from also owning the contract and failure behavior of Submission API. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Remote domain remains unavailable for days” to the external caller. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Mail Client boundary before extracting or scaling it. |
| Submission API | Owns authentication, validation, quotas, deadlines, and routing. In this design it participates in: Expand recipients, filter policy/malware, and create independent delivery records. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Mail Client from also owning the contract and failure behavior of SMTP Ingress. | Put protocol, authentication, quotas, and business transitions in one process. Acceptable at low scale, but it couples external traffic risk to domain releases. Here that simpler choice would couple “Recipient expansion creates huge fan-out” to Mail Client. | Costs another hop, policy distribution, and a high-blast-radius fleet. Introduce it when many clients or services need one protocol and protection boundary. Measure the latency, saturation, lag, or mismatch at the Submission API boundary before extracting or scaling it. |
| SMTP Ingress | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Schedule per-domain SMTP attempts with reputation, quotas, and exponential backoff. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Submission API from also owning the contract and failure behavior of Identity / DKIM. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Spam verdict changes after delivery” to Submission API. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the SMTP Ingress boundary before extracting or scaling it. |
| Identity / DKIM | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: On local delivery append mailbox entry and change cursor; external delivery records response. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents SMTP Ingress from also owning the contract and failure behavior of Spam / Malware. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Client retries submission after timeout” to SMTP Ingress. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Identity / DKIM boundary before extracting or scaling it. |
| Spam / Malware | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Process bounces/complaints idempotently and update reputation plus user-visible state. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Identity / DKIM from also owning the contract and failure behavior of Durable Mail Queue. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Mailbox index lags message delivery” to Identity / DKIM. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Spam / Malware boundary before extracting or scaling it. |
| Durable Mail Queue | Preserves durable ordering, replay, and consumer checkpoints. In this design it participates in: Authenticate submission and durably store the immutable MIME body. | Decouples bursts and failure from user acknowledgment. It prevents Spam / Malware from also owning the contract and failure behavior of Domain Scheduler. | Call every downstream consumer synchronously. That couples user latency and availability to analytics, notification, indexing, and audit dependencies. Here that simpler choice would couple “Remote domain remains unavailable for days” to Spam / Malware. | Costs eventual consistency, schema evolution, replay tooling, idempotent consumers, and lag operations. Earn it when bursts or downstream failure must not block acknowledgment. Measure the latency, saturation, lag, or mismatch at the Durable Mail Queue boundary before extracting or scaling it. |
| Domain Scheduler | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Expand recipients, filter policy/malware, and create independent delivery records. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Durable Mail Queue from also owning the contract and failure behavior of SMTP Egress. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Recipient expansion creates huge fan-out” to Durable Mail Queue. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Domain Scheduler boundary before extracting or scaling it. |
| SMTP Egress | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Schedule per-domain SMTP attempts with reputation, quotas, and exponential backoff. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Domain Scheduler from also owning the contract and failure behavior of Message Blob Store. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Spam verdict changes after delivery” to Domain Scheduler. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the SMTP Egress boundary before extracting or scaling it. |
| Message Blob Store | Owns authoritative versioned state or immutable evidence. In this design it participates in: On local delivery append mailbox entry and change cursor; external delivery records response. | Defines the source of truth and commit boundary. It prevents SMTP Egress from also owning the contract and failure behavior of Mailbox Metadata. | Let each service persist its own interpretation. That removes one clear commit boundary and makes retries, support, and reconciliation ambiguous. Here that simpler choice would couple “Client retries submission after timeout” to SMTP Egress. | Costs schema migration, replication, backup, and shard ownership. Split storage only when access patterns, retention, or compliance boundaries materially differ. Measure the latency, saturation, lag, or mismatch at the Message Blob Store boundary before extracting or scaling it. |
| Mailbox Metadata | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Process bounces/complaints idempotently and update reputation plus user-visible state. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Message Blob Store from also owning the contract and failure behavior of Thread / Search Index. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Mailbox index lags message delivery” to Message Blob Store. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Mailbox Metadata boundary before extracting or scaling it. |
| Thread / Search Index | Serves a low-latency, disposable projection with authoritative fallback. In this design it participates in: Authenticate submission and durably store the immutable MIME body. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Mailbox Metadata from also owning the contract and failure behavior of Push / IMAP Sync. | Read authoritative storage for every request. Simpler initially, but latency and source-of-truth load scale together and a hot key becomes a database incident. Here that simpler choice would couple “Remote domain remains unavailable for days” to Mailbox Metadata. | Costs invalidation, staleness, stampede protection, and memory. Add or split it only after the workload (10B messages/day · 50 MB attachments · minutes of retry) proves repeated reads dominate. Measure the latency, saturation, lag, or mismatch at the Thread / Search Index boundary before extracting or scaling it. |
| Push / IMAP Sync | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Expand recipients, filter policy/malware, and create independent delivery records. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Thread / Search Index from also owning the contract and failure behavior of Bounce Processor. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Recipient expansion creates huge fan-out” to Thread / Search Index. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Push / IMAP Sync boundary before extracting or scaling it. |
| Bounce Processor | Executes idempotent asynchronous work under lease and retry policy. In this design it participates in: Schedule per-domain SMTP attempts with reputation, quotas, and exponential backoff. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Push / IMAP Sync from also owning the contract and failure behavior of Reputation Service. | Perform the work before acknowledging the caller. This gives simpler consistency but unbounded tail latency and fragile retries. Here that simpler choice would couple “Spam verdict changes after delivery” to Push / IMAP Sync. | Costs leases, checkpoints, retries, DLQs, and lag operations. Separate once execution time or burstiness no longer fits the request deadline. Measure the latency, saturation, lag, or mismatch at the Bounce Processor boundary before extracting or scaling it. |
| Reputation Service | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: On local delivery append mailbox entry and change cursor; external delivery records response. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Bounce Processor from also owning the contract and failure behavior of Audit / Abuse. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Client retries submission after timeout” to Bounce Processor. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Reputation Service boundary before extracting or scaling it. |
| Audit / Abuse | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Process bounces/complaints idempotently and update reputation plus user-visible state. | Proves correctness and supports controlled recovery. It prevents Reputation Service from also owning the contract and failure behavior of operators and repair tooling. | Infer correctness from request logs. Logs do not prove durable business state, detect silent drift, or safely repair ambiguous outcomes. Here that simpler choice would couple “Mailbox index lags message delivery” to Reputation Service. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Audit / Abuse boundary before extracting or scaling it. |