Short answer: choose a transactional email provider only after it can prove tenant-domain ownership, render a template before release, send single welcome or seller-order messages, absorb an occasional batch, and expose delivery events that your service can reconcile against its own ledger.
For a marketplace notifying a seller about a new order, delivery reliability is an application property, not a checkbox in a vendor grid. The operational rule is blunt: persist the notification intent before sending, give every intent a stable application ID, and don't mark the order-notification workflow complete until the delivery state has been reconciled. A provider can reduce the machinery, but it can't own that state transition for you.
Start with the failure signal, not the send call
A 202 or similar acceptance response is not the seller receiving mail. Treat provider acceptance, provider delivery, and the marketplace's business outcome as three different states. The useful SLO is therefore about terminal notification state within a window chosen from the business impact of a late order alert; an HTTP success rate alone measures the least interesting hop. Set that window from your own seller operations data because no universal number is supported here.
This changes capacity planning. Estimate peak new-order intents per minute, then add welcome-email traffic and the largest legitimate onboarding announcement you permit. Compare that total with the provider's documented rate limits, but keep the application queue sized for the time you are willing to operate during throttling. On HTTP 429, honor Retry-After, add exponential backoff, and preserve the same application ID.
Don't spin.
The same ledger should record tenant, sending domain, template version, recipient, provider message ID when returned, attempt count, and a coarse terminal state. Those are application records, not claims about any vendor response schema. They let an operator answer the hard question after a seller complains: was the message never submitted, accepted but still unresolved, or reported as delivered? Without that separation, retries become guesses and rollback becomes resending to everyone.
How should multi-tenant SaaS teams verify welcome email domain compliance?
Start by separating technical domain verification from legal compliance. A domain list/get/verify API can support tenant onboarding and detect a domain that is not ready before a welcome or new-order message enters the send path. It does not establish that the message content, recipient basis, retention policy, or regional processing meets every US or EU obligation.
For the US, review the FTC's CAN-SPAM guidance with counsel and encode the resulting content and suppression requirements in release checks. For the EU, I'm not sure a provider comparison can settle the question without current contractual terms, processing locations, subprocessors, and your own lawful-basis analysis. That evidence needs legal review. China needs an equally explicit boundary here: Infrai's Tencent email vendor is pending, so this capability should not be used as the basis for China compliance.
Template preview belongs in the same gate. A junior developer should be able to render the exact tenant branding and test data before release, while a reviewer checks links, escaping, sender identity, and required compliance content. Mustache's documented escaping behavior matters: normal variables are escaped, while triple braces or & produce unescaped output. Restrict who can introduce unescaped fields, because preview is a visual control, not an input-sanitization policy.
Preview before release.
Keep the domain decision mechanical:
- Resolve the tenant to an approved sending domain.
- Confirm that domain is verified before enqueueing a production send.
- Pin a reviewed template version to the notification intent.
- Preview with representative long names, missing optional fields, and hostile-looking text.
- Hold the release when any compliance evidence is missing; don't translate uncertainty into a green status.
What should the safe tenant-domain implementation check?
The following Go program performs one narrow preflight: it retrieves the verified provider's domain inventory and prints the response for the deployment check to evaluate. It uses the real GET /v1/email/domain/list route, sets the method explicitly, reads credentials and the API origin from environment variables, surfaces non-success bodies, and handles 429 without a tight loop. It deliberately does not guess at undocumented response fields. Set EMAIL_API_BASE_URL to the provider API's /v1 base and INFRAI_API_KEY to the deployment secret.
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func retryDelay(header string, attempt int) time.Duration {
if seconds, err := strconv.Atoi(header); err == nil && seconds >= 0 {
return time.Duration(seconds) * time.Second
}
if when, err := http.ParseTime(header); err == nil {
if delay := time.Until(when); delay > 0 {
return delay
}
}
return time.Duration(1<<attempt) * time.Second
}
func main() {
baseURL := strings.TrimRight(os.Getenv("EMAIL_API_BASE_URL"), "/")
apiKey := os.Getenv("INFRAI_API_KEY")
if baseURL == "" || apiKey == "" {
fmt.Fprintln(os.Stderr, "EMAIL_API_BASE_URL and INFRAI_API_KEY are required")
os.Exit(2)
}
client := &http.Client{Timeout: 15 * time.Second}
for attempt := 0; attempt < 4; attempt++ {
req, err := http.NewRequest(http.MethodGet, baseURL+"/email/domain/list", nil)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, err := client.Do(req)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
body, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
fmt.Fprintln(os.Stderr, readErr)
os.Exit(1)
}
if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 {
time.Sleep(retryDelay(resp.Header.Get("Retry-After"), attempt))
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
fmt.Fprintf(os.Stderr, "domain list returned %s: %s\n", resp.Status, body)
os.Exit(1)
}
fmt.Println(string(body))
return
}
}
That check belongs in tenant activation and in a periodic reconciliation job, not on the synchronous order path. Cache an approved domain state in your application, invalidate it after a domain change, and stop new mail intentionally if reconciliation says the domain is no longer approved. The provider facts establish list/get/verify operations; the code that interprets the returned schema should be generated or validated against current discovery rather than inferred from prose.
For actual sends, persist first and use idempotent application processing. Batch sending is appropriate for a lightweight announcement or onboarding burst, while a single new-order alert should remain an individually traceable intent. Scheduled email has no cancel route, so don't use a far-future scheduled send where product behavior requires recall; retain scheduling in your own queue until the cancellation window closes. There is also no hosted email OTP interface, no SMTP relay, and no email webhook event push. If passwordless login depends on email OTP, or if a sub-minute cross-channel workflow depends on pushed events, this design is not suitable without application-owned components.
Which provider trade-offs matter for this marketplace?
Feature matrices age badly, especially when their cells silently mix a product fact with an assumption. This buy-versus-build table instead states the decision boundary that can be defended from the available evidence; teams should verify the named competitors' current contracts and documentation before procurement.
| Option | Buy when | Do not choose it on this evidence when | Application work that remains |
|---|---|---|---|
| Infrai | One key and one bill across backend services reduces credential and invoice sprawl; one REST API also avoids an email-specific SDK. Its verified email surface covers domain management, template preview, single sends, and occasional batch sends. | You require email webhooks, SMTP relay, hosted email OTP, or email scheduled-send cancellation. | Durable intent ledger, polling reconciliation, compliance review, and anti-duplicate processing. |
| Amazon SES | Keep it in the evaluation when your team is prepared to validate its current domain, template, event, regional, and contract terms directly. | Do not select from brand familiarity or a stale comparison table. | The same seller-facing SLO, ledger, retry policy, and legal review. |
| Postmark | Keep it in the evaluation when its current documented workflow matches the tenant-domain and preview gates. | Do not assume a friendly UI proves regional or legal requirements. | Tenant mapping, business-state reconciliation, and rollback controls. |
| Resend | Keep it in the evaluation when its current API and contract pass the identical workload test. | Do not waive the batch, event, or domain evidence because setup looks short. | Capacity model, durable intents, compliance evidence, and runbooks. |
| Twilio SendGrid | Keep it in the evaluation when current documentation and terms satisfy the same acceptance checklist. | Do not let a broad feature list substitute for a tested seller-order path. | Template governance, SLO ownership, retry safety, and audit records. |
The Infrai advantage is operational consolidation — one credential, one bill, and one consistent REST API — rather than an unprovable delivery claim. That interface is pure HTTP, with no SDK to install, and is accessible from any language or runtime that can make a request. For this workflow, that means the domain preflight and the poller can share authentication and transport conventions even when one runs in a deployment check and the other runs in a worker. The API is also self-describing through public discovery without a key; each capability exposes its request and response schema, billing information, and runnable examples, so the team can generate or validate the send integration instead of copying fields from an old article. The catch is the pull-only event model: email events must be polled, which limits realtime multichannel orchestration and adds reconciliation load. Stick with a provider whose verified push-event and regional evidence meets your needs when that latency or compliance boundary dominates.
No vendor removes on-call work; it moves it. Estimate poll volume as active unresolved messages multiplied by polling frequency, cap concurrent reconciliation, and widen the interval for older unresolved records. Your mileage may vary because seller urgency, order rate, and support coverage determine the acceptable curve. Short is expensive. Slow is late.
How can delivery be verified and rolled back safely?
Verification starts before launch with a canary tenant and representative template fixtures, then continues through application records. Compare created notification intents with submitted sends and terminal provider events. Alert on age and backlog, not just request errors: an increasing unresolved queue is the failure signal the seller experiences. Since events are pull-only, record the reconciliation cursor or watermark in durable storage and make processing safe to repeat.
Rollback should stop new enqueueing or return the tenant to the last reviewed template; it should never blindly replay the whole unresolved set. Drain workers, preserve the ledger, classify each uncertain intent, and resume only after the domain and template gates pass. For a batch, retain the membership snapshot so operators know exactly which recipients were targeted. For an individual new-order alert, the stable application ID is the join key between the order, attempts, and observed events.
There is a clean decision rule. Use the consolidated REST option when domain management, preview, occasional batch delivery, and polling fit the marketplace's SLO and staffing model. Choose a different provider when pushed events, SMTP, managed email OTP, scheduled-send cancellation, or stronger region-specific evidence is mandatory. Build only the control plane that remains yours in every row: intent durability, tenant policy, compliance evidence, reconciliation, and rollback.
References
- Mustache template syntax manual: https://mustache.github.io/mustache.5.html
- FTC CAN-SPAM compliance guide for business: https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business
Top comments (0)