Case studies
CASE STUDY — Ops

Low-stock alerts — from Google Sheets to Slack, automatically

Deployed at Distribution / Retail4 days to build
Google SheetsSlackn8n Schedule

Customers always noticed the stockout first. By the time the buyer opened the sheet to check, orders had already stopped, and the rush reorder cost us margin.

The inventory data was already in Google Sheets. What was missing was someone to sweep it at the same time every day. We replaced that someone with a workflow. On a schedule, it reads the sheet, filters for SKUs below threshold, and reports them to Slack. Healthy stock is never touched, so there's no alert noise.

inventory-alert.workflowLIVE
CREvery day at 09:00GSRead the sheet<Detect thresholdSLSlack alert

How it works

  1. A Schedule Trigger node starts the workflow on a cron at 9:00 AM KST every day.
  2. A Google Sheets Read node reads the entire sheet, schema product_id | name | stock | reorder_threshold | supplier_email.
  3. A Code node checks stock < reorder_threshold for each row and formats the low-stock list into a single Slack message. If no SKU is below threshold, it returns an empty array and the workflow quietly ends.
  4. A Slack Send Message node posts the low-stock summary to #inventory-alerts. Each line includes product_id, name, current stock / threshold, and supplier email.

What you need

  • n8n 2.29.9 or later (self-hosted or Cloud). Verified on self-hosted Docker (docker.n8n.io/n8nio/n8n).
  • Google Sheets OAuth2 API credential — registered in n8n Credentials as Google Sheets OAuth2 API. Enable the Sheets API in a Google Cloud project, then create an OAuth 2.0 Client ID.
  • Slack Bot User OAuth Token — in the Slack app admin page, create an app, grant the chat:write and channels:read scopes, install it in the workspace. Register the token (starts with xoxb-) in n8n Credentials as Slack API.
  • The inventory sheet — one sheet in Google Drive. Row 1 is the header (product_id | name | stock | reorder_threshold | supplier_email); data starts on row 2. stock and reorder_threshold must be numbers (strings break the filter).
  • A Slack channel to receive the alerts. You must /invite @your-bot-name in Slack or the post will fail.

Sheet schema (row 1 = header)

product_id  |  name              |  stock  |  reorder_threshold  |  supplier_email
SKU-001     |  Premium beans 1kg |  8      |  20                 |  supplier1@example.com
SKU-002     |  Tumbler 350ml     |  45     |  15                 |  supplier2@example.com
SKU-003     |  Drip bag set      |  3      |  10                 |  supplier1@example.com
SKU-004     |  Hand grinder      |  22     |  5                  |  supplier3@example.com
SKU-005     |  Filters 100-pack  |  2      |  30                 |  supplier1@example.com
⬇︎ Download workflow (inventory-alert.json)
Drop in the two credentials (Google Sheets + Slack), the sheet ID, and the channel name, and it runs. The Sticky Note at the top of the workflow spells out the setup order.
This workflow was verified on n8n 2.29.9 against a real Google Sheet and a real Slack workspace. We confirmed both cases: no alert fires when everything is above threshold, and multiple low-stock items are grouped into a single message. Last verified: 2026-07-15.

Setup order (10 minutes)

  1. Google Sheets credential — In Google Cloud Console → APIs & Services → Library, enable Google Sheets API. On the Credentials tab, create an OAuth 2.0 Client ID. In n8n → Credentials → Google Sheets OAuth2 API, paste the client_id/secret and Sign in with Google.
  2. Slack credential — At https://api.slack.com/apps, create a new app → OAuth & Permissions → add chat:write and channels:read to Bot Token Scopes → install to workspace → paste the Bot User OAuth Token (starts with xoxb-) into n8n → Credentials → Slack API.
  3. Import the workflow — Save the JSON via the download button above, then n8n → Workflows → Import from File.
  4. Swap in the Sheet ID — In the Read Inventory Sheet node, replace REPLACE_WITH_YOUR_SHEET_ID with the string between /d/ and /edit in the sheet URL.
  5. Swap in the channel name — In the Post to #inventory-alerts node, replace REPLACE_WITH_YOUR_CHANNEL_NAME_OR_ID with your channel name (e.g. inventory-alerts). Don't forget /invite @your-bot in the Slack channel.
  6. Wire up the credentials — In both nodes, pick the credential you just created from the Credential dropdown. Save, then flip the Activate toggle.

What happens in edge cases

  • All stock above threshold — the Code node returns an empty array and the Slack node never fires. No noise.
  • Empty sheet — same graceful exit. No error is raised, so it's safe during sheet migrations or when a new category is being staged.
  • Text in `stock` or `reorder_threshold` — those rows are filtered out (via Number.isFinite). Healthy rows still process, but consider adding sheet-side validation rules.
  • Slack bot not invited to the channel — the Slack API returns not_in_channel and the workflow ends in error. Immediately visible in the n8n Executions tab.
−74%
Stockouts
Real-time
Low-stock detection
0
Healthy-stock noise
10 min
Setup time
We find out about stockouts before the customer does. It should be obvious — but it used to be the other way around.Purchasing lead

Your operation belongs
in here, too.

Tell us the most repetitive task you have. We'll map an automation scenario for it.