Set up external alerts in Retool using Retool Workflows — create a Workflow with a schedule or webhook trigger, add a condition block to check your data threshold, then use the Email block or HTTP Request block (for Slack/Teams webhooks) to send the alert. In-app notifications use utils.showNotification(); external alerts require Workflows.
| Fact | Value |
|---|---|
| Tool | Retool |
| Difficulty | Beginner |
| Time required | 20-25 min |
| Compatibility | Retool Cloud and Self-hosted |
| Last updated | March 2026 |
External Alerts vs In-App Notifications in Retool
Retool has two notification systems. In-app notifications (utils.showNotification()) are toast messages that appear inside the Retool app while a user is actively using it. External alert notifications go to email, Slack, Teams, or mobile push — they reach users even when they're not in the app.
External alerts require Retool Workflows, Retool's automation engine for running server-side logic on a schedule or in response to triggers. This tutorial covers building alert workflows for the most common patterns: scheduled data threshold checks, event-triggered Slack messages, and email digest reports.
Prerequisites
- Retool account with Workflows access (available on paid plans)
- For email alerts: SMTP resource configured in Settings → Resources, or Retool's built-in email block
- For Slack alerts: a Slack Incoming Webhook URL from api.slack.com
- For email: recipient addresses and knowledge of the alert trigger condition
Step-by-step guide
Create a Retool Workflow
Navigate to the Workflows section (main sidebar or retoolapp.com/workflows). Click '+ New Workflow'. A Workflow consists of blocks connected in a flow. The first block is always a Trigger — you choose how the workflow starts: on a schedule, via a webhook, or triggered from an app. Workflows run server-side and can query databases, call APIs, send emails, and execute JavaScript — all without a user present in the app.
Expected result: A new Workflow editor opens with an empty canvas showing the first Trigger block.
Set Up a Schedule Trigger for Periodic Checks
For threshold-based alerts (e.g. check inventory every hour), use a Schedule trigger. Click the Trigger block and select 'Schedule'. Configure the frequency — options include every N minutes, hourly, daily at a specific time, or a cron expression for complex schedules. For an inventory alert: run every hour. For a daily digest: run at 8:00 AM in the recipient's timezone.
1// Example cron expressions for the Schedule trigger:2// Every hour at :00: 0 * * * *3// Daily at 8 AM UTC: 0 8 * * *4// Weekdays at 9 AM: 0 9 * * 1-55// Every 30 minutes: */30 * * * *67// If using UTC time in cron, adjust for your timezone:8// 8 AM Eastern (UTC-5) = 1 PM UTC = 0 13 * * *Expected result: The workflow is scheduled to run at the configured interval automatically.
Query Your Database for Alert Conditions
Add a Query block (Resource Query) to the workflow canvas. Connect it after the trigger. Select your database resource and write a SQL query that returns the data you want to check for alert conditions. For inventory alerts: query items below threshold. For error monitoring: query recent error logs. The query result is available in subsequent blocks as blocks.queryBlockName.data.
1-- SQL Query block: checkLowInventory2-- Returns items where stock_quantity < reorder_level3SELECT4 p.id,5 p.name,6 p.sku,7 p.stock_quantity,8 p.reorder_level9FROM products p10WHERE11 p.stock_quantity < p.reorder_level12 AND p.is_active = true13ORDER BY (p.reorder_level - p.stock_quantity) DESC;Expected result: The workflow query block returns items requiring attention, or an empty array if no alert is needed.
Add a Condition Block to Avoid Unnecessary Alerts
Add a 'Condition' (or 'Branch') block after the query to check whether an alert is actually needed. If there are no low-inventory items, stop the workflow — don't send an alert email for nothing. This is the 'early exit' pattern. In the Condition block, set the condition to check if the query returned any rows.
1// Condition block expression:2// Check if any low-inventory items were found:3{{ blocks.checkLowInventory.data.length > 0 }}45// If TRUE → continue to alert notification6// If FALSE → end workflow (no alert needed)78// For numeric threshold checks:9{{ blocks.getMetrics.data[0].error_rate > 0.05 }}10// Alert only if error rate exceeds 5%Expected result: The workflow skips notification blocks and ends silently when no alert condition is met.
Send an Email Alert
Add an Email block (or use an SMTP Resource Query) to send the alert email. Configure the To, Subject, and Body fields. Use {{ blocks.queryBlockName.data }} to include dynamic data from your query in the email body. Retool Workflows include a built-in Email block that uses Retool's email infrastructure — no SMTP setup needed for Retool Cloud. For self-hosted or custom email, configure an SMTP resource.
1// Email block configuration:2// To: ops-team@yourcompany.com3// Subject: ⚠ Low Inventory Alert - {{ new Date().toLocaleDateString() }}4// Body (HTML):56`<h2>Low Inventory Alert</h2>7<p>${blocks.checkLowInventory.data.length} items are below reorder level:</p>8<table border="1" cellpadding="5">9 <tr><th>SKU</th><th>Name</th><th>Current Stock</th><th>Reorder Level</th></tr>10 ${blocks.checkLowInventory.data.map(item =>11 `<tr>12 <td>${item.sku}</td>13 <td>${item.name}</td>14 <td style="color:red">${item.stock_quantity}</td>15 <td>${item.reorder_level}</td>16 </tr>`17 ).join('')}18</table>19<p>Please reorder these items.</p>`Expected result: An HTML email with a table of low-inventory items is sent to the configured recipient.
Send a Slack Alert via Incoming Webhook
Create a Slack Incoming Webhook at api.slack.com/apps → Your App → Incoming Webhooks. Copy the webhook URL. In the Retool Workflow, add an HTTP Request block (or REST API Resource Query) and POST the alert message to the Slack webhook URL. Slack messages use Block Kit JSON format for rich formatting. Store the webhook URL in a Retool environment variable for security.
1// HTTP Request block configuration:2// Method: POST3// URL: {{ retoolContext.configVars.SLACK_WEBHOOK_URL }}4// Body (JSON):56{7 "text": "⚠️ Low Inventory Alert",8 "blocks": [9 {10 "type": "header",11 "text": {12 "type": "plain_text",13 "text": "⚠️ Low Inventory Alert"14 }15 },16 {17 "type": "section",18 "text": {19 "type": "mrkdwn",20 "text": "*{{ blocks.checkLowInventory.data.length }} items* are below reorder level:"21 }22 },23 {24 "type": "section",25 "text": {26 "type": "mrkdwn",27 "text": "{{ blocks.checkLowInventory.data.map(i => `• *${i.name}* (SKU: ${i.sku}) — ${i.stock_quantity} remaining`).join('\n') }}"28 }29 }30 ]31}3233// Store SLACK_WEBHOOK_URL in:34// Settings → Configuration Variables (mark as Secret)Expected result: A formatted Slack message appears in the configured channel with a list of low-inventory items.
Trigger an Alert Workflow from a Retool App
In addition to scheduled triggers, you can trigger a Workflow directly from a Retool app using the Workflow resource query type. Create a resource query in your app with type 'Retool Workflows', select your alert workflow, and trigger it when a specific app event occurs (e.g. when a user marks an order as critical). This bridges in-app events with external notification workflows.
1// In a Retool app, create a Resource Query:2// Resource: Retool Workflows3// Workflow: alert-workflow-name4// Trigger endpoint: /trigger (or your webhook endpoint)56// JS Query in the app:7await triggerAlertWorkflow.trigger({8 additionalScope: {9 orderId: table1.selectedRow.id,10 reason: reasonInput.value,11 severity: severitySelect.value12 }13});1415utils.showNotification({16 title: 'Alert sent',17 description: 'The operations team has been notified.',18 notificationType: 'success'19});Expected result: Clicking a button in your app triggers the Workflow, which sends the external alert, and confirms to the user with an in-app notification.
Complete working example
1// Retool Workflow: inventoryAlertWorkflow2// Trigger: Schedule — every hour (cron: 0 * * * *)3// Blocks:45// Block 1: checkLowInventory (Resource Query — PostgreSQL)6// SQL:7SELECT id, name, sku, stock_quantity, reorder_level8FROM products9WHERE stock_quantity < reorder_level AND is_active = true10ORDER BY (reorder_level - stock_quantity) DESC;1112// Block 2: shouldAlert (Condition)13// Expression: {{ blocks.checkLowInventory.data.length > 0 }}14// If TRUE → continue15// If FALSE → end workflow1617// Block 3: buildMessage (Code — JavaScript)18const items = blocks.checkLowInventory.data;19const itemList = items20 .map(i => `• ${i.name} (${i.sku}): ${i.stock_quantity} / ${i.reorder_level} min`)21 .join('\n');22const subject = `⚠ ${items.length} item(s) need reordering`;23return { itemList, subject, count: items.length };2425// Block 4: sendSlack (HTTP Request)26// POST {{ retoolContext.configVars.SLACK_WEBHOOK_URL }}27// Body:28// {29// "text": "{{ blocks.buildMessage.data.subject }}",30// "attachments": [{"text": "{{ blocks.buildMessage.data.itemList }}", "color": "warning"}]31// }3233// Block 5: sendEmail (Email)34// To: inventory@company.com35// Subject: {{ blocks.buildMessage.data.subject }}36// Body: HTML table of itemsCommon mistakes
Why it's a problem: Sending alerts on every scheduled run even when there's nothing to report
How to avoid: Add a Condition block after the query check: {{ blocks.checkData.data.length > 0 }}. Connect the 'false' branch to an End block so the workflow exits silently when there's nothing to alert.
Why it's a problem: Hardcoding the Slack webhook URL in the HTTP Request block body
How to avoid: Store the webhook URL as a Secret configuration variable: Settings → Configuration Variables. Access it as {{ retoolContext.configVars.SLACK_WEBHOOK_URL }}. Hardcoded webhook URLs are easily exposed and hard to rotate.
Why it's a problem: Confusing utils.showNotification() with external alert notifications
How to avoid: utils.showNotification() only shows in-app toast messages to currently active users. For notifications that reach users when they are not in Retool, use Retool Workflows to send email or Slack messages.
Why it's a problem: Building complex alert logic in a Workflow without testing it first
How to avoid: Always click 'Run' in the Workflow editor to test the flow manually before activating the schedule. Check each block's output to verify data shapes and conditions are working correctly.
Best practices
- Always add a Condition block before notification blocks — don't send alerts when there's nothing to report, to avoid alert fatigue.
- Store webhook URLs and email credentials in Retool configuration variables marked as Secret — never hardcode them in Workflow blocks.
- Use a dedicated notification email address or Slack channel for alerts rather than personal addresses, so the team handles alerts collectively.
- Include a direct link back to the relevant Retool app in alert emails: 'View in Retool: https://yourorg.retool.com/apps/inventory'.
- Add rate limiting logic to avoid sending duplicate alerts — check whether an alert was recently sent before firing again.
- Test Workflows in Retool's Workflow editor by clicking 'Run' manually before activating the schedule, to verify the output without waiting for the next scheduled run.
- For critical alerts, send to multiple channels (email AND Slack) to ensure delivery.
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I'm building a Retool Workflow that sends a Slack alert when inventory drops below the reorder level. The workflow runs every hour on a schedule. Write the flow: (1) SQL query that finds products where stock_quantity < reorder_level, (2) a condition that exits the workflow if no items are found, (3) a JavaScript code block that builds a formatted message string from the query results, and (4) an HTTP Request block that POSTs to a Slack Incoming Webhook URL stored in a Retool config variable. Include the Slack Block Kit JSON format for the message.
Create a Retool Workflow named 'inventoryAlert' with: (1) Schedule trigger running every hour, (2) Resource Query block checking for products where stock_quantity < reorder_level, (3) Condition block that stops if no low-stock items found, (4) HTTP Request block sending to {{ retoolContext.configVars.SLACK_WEBHOOK_URL }} with a formatted list of low-stock items. Also show how to trigger this workflow from a Retool app button using a Workflows resource query.
Frequently asked questions
What plan does Retool Workflows require?
Retool Workflows is available on paid plans. The Free plan does not include Workflows. Check your plan at retool.com/pricing — Business and Team plans include Workflows. Self-hosted Retool requires a separate Workflows license.
How do I send a Slack notification from Retool without a Workflow?
You can send Slack messages directly from a Retool app using a REST API Resource Query configured with your Slack webhook URL. Set up a REST resource for Slack, then trigger it with an event handler or JS Query. This is synchronous and requires a user to be in the app — for scheduled or automated alerts, Workflows are required.
Can I send mobile push notifications from Retool?
Mobile push notifications are available through Retool Mobile on the Business plan and above. In your Retool Mobile app, configure push notification channels in the Mobile app settings. Trigger pushes from Workflows using the Push Notification block. Standard Retool web apps do not support browser push notifications natively.
How do I avoid duplicate alerts when the same condition persists across multiple workflow runs?
Track the last alert time in a database table or Retool Database. At the start of your workflow, query whether an alert was sent in the last N hours for the same condition. Add this as an additional condition: only send the alert if no alert was sent recently. Update the last_alerted_at timestamp after each successful alert.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation