Core concepts
Routing rules
Routing rules pick which destination handles each send. Without any rules, every message goes to the user's single default destination (the first active one). With rules, you can route by sender, recipient domain, category, or arbitrary metadata.
Rule shape
Each rule has:
- Priority (integer): lower numbers win first. Two rules with the same priority are evaluated in creation order.
- Match field:
sender,recipient,category, ormetadata.<key>. The metadata branch lets you route on any field your app sticks on the message (metadata.tenant_id,metadata.environment, etc.). - Match operator:
equals,contains,starts_with, orregex. - Match value: the string to compare against. For
regex, a Go-style regular expression. - Destination id: where matched messages go.
- Environment (optional):
liveorsandbox. Only matches when the message's environment matches. - Enabled (boolean): toggle without deleting.
Rules are scanned in priority order; the first match wins.
Common patterns
Route by category
You want transactional sends through Postmark and marketing through Mailgun:
priority 10 category equals "transactional" -> postmark-prod
priority 20 category equals "marketing" -> mailgun-prod
priority 99 match-all -> smtp-fallbackThe match-all rule is the safety net set match_field to category and match_op to contains with an empty value, or pick any field you know will be present.
Route by recipient domain
Internal recipients (@yourcompany.com) through your in-house SMTP host, everyone else through a cloud provider:
priority 10 recipient contains "@yourcompany.com" -> internal-smtp
priority 99 category contains "" -> ses-prodRoute by metadata
You're multi-tenant and each tenant has their own destination:
priority 10 metadata.tenant_id equals "acme" -> acme-postmark
priority 20 metadata.tenant_id equals "globex" -> globex-resend
priority 99 category contains "" -> shared-smtpRoute by environment
Sandbox sends through a captured-only destination, production through the real one:
priority 10 environment = sandbox category contains "" -> sandbox-capture
priority 20 environment = live category contains "" -> ses-prodAuthoring rules
The dashboard route is `/destinations/routing`. The same can be done via the MCP server:
email_routing_rule_create(field, op, value, destination_id, priority, environment?)email_routing_rule_list()see the current chain in priority order.email_routing_rule_reorder(ordered_ids)bulk-set priority ordering.email_routing_rule_delete(id)
Debugging
The trace event routing_decision carries the matched rule's id in its payload. If a send went to the wrong destination, open the trace and look at the routing decision the rule id tells you which row won.
If no rule matched, the payload reads reason: "default" and the destination is the user's default. Add a match-all rule at the bottom of the chain to make the routing explicit.