How to Set Up Multi-Channel Notifications (Email + Slack)
Send notifications to both email and Slack simultaneously from a single workflow.
What This Integration Does
Important events deserve more than one channel. Stakeholders who live in email want a digestible message in their inbox, while the on-call team wants something immediate in Slack. Building two separate workflows for the same event is wasteful and drifts out of sync over time. This pattern fans a single trigger out to both channels at once and keeps the content consistent.
The run model is simple: a Trigger fires once per event, a Parallel node fans the payload out into concurrent branches, and each branch hands the message to its own delivery connector. There is no shared state to manage after the run finishes - each branch either succeeds or surfaces its own error, and the workflow records both outcomes in the execution log.
Prerequisites
- A slack connection with permission to post in the target channel (chat:write and channels:read).
- A resend connection with a verified sending domain, or an smtp connection for outbound mail.
- The Slack channel ID (not just the name) and the recipient email address or distribution list.
Step 1: Trigger
Drop a Trigger node and pick the sub-type that fits the event. Webhook works for upstream systems posting to Spojit, Schedule for periodic digests, and Manual when an operator kicks it off. Map the incoming payload into named variables like eventTitle, eventBody, and severity so the downstream branches can reference them cleanly.
Step 2: Transform - Build the Message Once
Add a Transform node before the fan-out. Compose both an HTML-friendly body for email and a short Slack-friendly summary in one place so the two channels do not drift. Output something like:
{
"subject": "[{{ severity }}] {{ eventTitle }}",
"emailHtml": "<h2>{{ eventTitle }}</h2><p>{{ eventBody }}</p>",
"slackText": ":rotating_light: *{{ eventTitle }}*\n{{ eventBody }}"
}
Step 3: Parallel Fan-Out
Add a Parallel node with two branches. Both branches will run concurrently and the workflow waits for both to finish before continuing. This is the key node that prevents the email step from blocking the Slack alert (or vice versa) when one channel is slow.
Step 4: Branch A - Send Email
In the first branch, add a Connector node pointing at the resend connector and pick the send-email tool. Set to, from, subject to {{ subject }}, and html to {{ emailHtml }}. If you do not use Resend, swap in the smtp connector with the same send-email tool - the field names are nearly identical.
Step 5: Branch B - Post to Slack
In the second branch, add a Connector node pointing at the slack connector and pick the send-message tool. Set channel to the channel ID and text to {{ slackText }}. For high-severity events, optionally chain a second slack step using add-reaction with an emoji like rotating_light on the message timestamp returned by the previous step.
Step 6: Confirm and Log
After the Parallel node closes, add a Condition node that checks both branch results. If either failed, route to a secondary fallback (a second Slack channel or a paging system). The execution log captures the per-branch outcome so you can audit delivery later.
Tips
- Keep the Slack message short - Slack truncates long blocks and on-call teams skim. Put detail in the email.
- Use Slack channel IDs (
C0123ABCD) rather than names. Names can be renamed and break the workflow silently. - If the same event can fire many times in a minute, debounce upstream or add a Condition that skips repeated alerts within a window.
Common Pitfalls
- Sending from an unverified Resend domain - the email silently goes to spam. Verify the domain first with
verify-domain. - Hard-coding Slack channel names in production. Use a workflow variable so dev and prod can point at different channels without editing the canvas.
- Treating one branch's failure as the whole workflow's failure. The Parallel node returns results for both - check each branch explicitly.
Testing
Run the workflow manually with a test payload aimed at a private Slack channel and your own email. Confirm both arrive within a few seconds of each other, then aim the production channel and recipient list before turning the trigger on.