Skip to content
Architecture

How to manage transactional email across multiple apps and domains

Build an inventory and a repeatable setup that still makes sense when the second app becomes the tenth.

THE SHORT ANSWER

Give each app its own project, credentials, sending identities, and operational records. Share the workspace where it helps administration, but make every send traceable to one app and environment. Project separation alone does not guarantee separate sender reputation.

Begin with an inventory you can actually maintain

The hard part of running several small apps is usually remembering which domain, API key, webhook endpoint, and allowance belongs to each one. A single unlabelled provider key makes the first integration easy and the fifth incident confusing.

Create one row per app and environment. Store references to secrets, never the secret values. Include an owner who can decide whether sending should be paused when something goes wrong. An app that is no longer actively developed still needs a contact for domain renewal and credential rotation.

App / environmentSending identityCredential referenceOperational owner
Atlas / Testhello@example.testsecrets/atlas/testApplication team
Atlas / Livereceipts@atlas.examplesecrets/atlas/liveApplication team
Beacon / Livenotify@beacon.examplesecrets/beacon/liveBeacon maintainer

Separate access before separating infrastructure

A key used by Atlas should not be able to inspect Beacon’s messages or change its templates. Scope keys to one project and the minimum capabilities required. A sending process rarely needs permission to manage domains or read inbound attachments.

Use separate Test and Live credentials and deployment secret names. A development machine should not inherit the production key just because both apps share an account. Make the environment visible in logs, dashboards, and support notes.

Operational separation is not complete reputation isolation. Projects may still use shared provider infrastructure, accounts, limits, or IP pools. Treat isolation claims as specific properties to verify, not as a consequence of having separate tabs.

Plan the visible sender and the return path

For each app, record the visible From domain, the DKIM signing domain, and the envelope/return-path domain. These can differ. Keeping their purpose explicit makes authentication errors easier to diagnose.

A sending subdomain can help organize a service, but do not casually replace the root domain’s MX records. Those records may already route employee mail. Apply the exact records supplied for your provider and preserve unrelated records.

When changing providers, inventory both old and new signing selectors and the return path. Validate a controlled message before retiring a still-used signing key. Domain verification in a dashboard is useful configuration evidence; it is not a measurement of every recipient’s inbox.

Understand SPF, DKIM, and DMARC alignment →

Use the same event contract across your apps

Define a small application envelope: project reference, environment, business event ID, template version, and recipient reference. Generate the business event once. Retries should not generate a new event ID or silently select a newer template.

An outbox in the application database lets a committed business event survive a temporary email outage. A sender processes the outbox and records the provider result. Keep unknown results distinct from definite rejection so recovery does not turn into duplicate sending.

Application outbox record · illustrativejson
{
  "app": "atlas",
  "environment": "test",
  "eventId": "order-42-receipt-v1",
  "templateVersion": "receipt-v3",
  "recipientRef": "customer-17",
  "state": "pending"
}

Build retry behavior around a stable event →

Make limits and incidents attributable

  • Set an explicit daily or monthly allowance for each app. A loop in one project should be visible before it consumes a shared budget.
  • Record provider event IDs with the project and environment. A delivery callback should never be attached to whichever project is currently selected in a user interface.
  • Keep suppression scope visible. A complaint restriction may be broader than one project; moving the send to another project is not a valid recovery strategy.
  • Choose retention based on operational needs. Keep identifiers and timestamps long enough to investigate while avoiding unnecessary long-term message content.
  • Write down who can pause sending, rotate credentials, and authorize a return to normal operation.

Add the next app with a repeatable checklist

Stampwing is being built around project-specific domains, keys, messages, templates, and operational visibility in one workspace. It is currently in early access preparation. You can use this checklist with your current email provider today.

  1. Create the project and its Test credential. Keep sample recipients and simulated results labelled.
  2. Exercise one successful queue acceptance, one validation error, and one ambiguous retry.
  3. Connect a signed webhook receiver and replay a duplicate event.
  4. Prepare the sending domain and inspect the actual authentication results of a controlled message before Live use.
  5. Set limits, ownership, retention, and an incident path. Save the setup record with the app’s deployment documentation.

Sources and further reading

Written for Stampwing with AI assistance and checked against the linked documentation. Examples are educational; simulated results are labelled. How these resources are maintained.