Message Scheduling and Reminders for Slack Ops Bots
Scheduled messages and reminders turn a reactive bot into a proactive one — maintenance windows, cert expiry, on-call nudges. Here's how to use them without spam.
- #slack
- #scheduling
- #reminders
- #automation
- #devops
- #chatops
Most Slack bots are reactive: you poke them, they respond. The bots that earn their keep are proactive — they tell you about the maintenance window before it starts, the cert that expires Friday, the on-call rotation that flips at 5pm. Slack gives you two primitives for this: scheduled messages and reminders. Used well, they make your ops bot feel like it’s looking ahead for you. Used badly, they’re just more noise. Here’s how I use them to build a bot that’s ahead of the team instead of behind it.
Two primitives, two jobs
chat.scheduleMessage posts a message to a channel at a future time. The bot owns it, it’s rich (Block Kit, buttons, threads), and it can be canceled or listed before it fires. This is your tool for announcements and prompts.
reminders.add creates a Slack reminder for a user or channel — the lightweight “remind me” you’d type by hand, but programmatic. It’s plain text, it nags the recipient through Slack’s native reminder UX, and it’s the right tool for personal nudges where you want Slack’s built-in snooze/complete behavior.
Pick based on whether you want a rich channel post (schedule a message) or a native personal nudge (add a reminder).
Scheduling a maintenance announcement
The classic use: announce a maintenance window ahead of time, automatically, from your change record.
// schedule a heads-up 1 hour before the window
const startsAt = Math.floor(window.start.getTime() / 1000);
const headsUp = startsAt - 3600;
const { scheduled_message_id } = await client.chat.scheduleMessage({
channel: '#ops-announcements',
post_at: headsUp,
text: `🔧 Maintenance on *${window.service}* starts in 1 hour`,
blocks: maintenanceBlocks(window),
});
// stash the id so you can cancel if the window gets rescheduled
await store.put(window.id, scheduled_message_id);
The detail that separates a good implementation from a frustrating one is cancelability. Change windows move. If you schedule the heads-up and then the window slips, you must cancel the old message (chat.deleteScheduledMessage) and schedule a new one — otherwise the channel gets a “starts in 1 hour” message for a window that already moved, and people stop trusting the bot.
async function reschedule(window, newStart) {
const oldId = await store.get(window.id);
if (oldId) {
await client.chat.deleteScheduledMessage({
channel: '#ops-announcements',
scheduled_message_id: oldId,
});
}
// ...schedule the new one
}
Cert and token expiry reminders
A genuinely useful proactive pattern: scan for things that expire — TLS certs, API tokens, cloud credentials — and schedule a reminder a week out, owned by whoever’s responsible.
for (const cert of expiringCerts) {
const remindAt = cert.notAfter - 7 * 86400; // 7 days before expiry
await client.reminders.add({
text: `🔐 Cert for ${cert.domain} expires in 7 days — rotate it`,
time: remindAt,
user: ownerSlackId(cert),
});
}
The win here is that the reminder lands on the responsible human’s desk with lead time, instead of becoming an incident at expiry. This is the kind of toil that’s invisible until it bites; scheduling it away is pure upside.
On-call handoff nudges
Schedule a message into the on-call channel at handoff time that names the incoming and outgoing engineers and links the runbook. Fire it at the rotation boundary pulled from PagerDuty or your schedule source. A predictable, automatic handoff prompt is how the baton actually gets passed instead of silently dropped.
Respect the recipient’s clock
Same rule as any scheduled bot: post_at is an absolute Unix timestamp, so “9am” means nothing until you resolve it against a timezone. For channel announcements, schedule against the team’s primary timezone. For personal reminders, use the user’s own timezone from users.info. Getting this wrong is how you ping someone at 3am about a cert — the fastest way to get your bot muted.
Don’t schedule what you can’t see
A pile of scheduled messages you can’t inspect is a liability. Use chat.scheduledMessages.list to enumerate what’s pending, and build a /scheduled command so the team can see — and cancel — upcoming bot posts. The day someone schedules a recurring announcement and goes on vacation, you’ll want a way to find and kill it without redeploying.
Recurrence is your job, not Slack’s
A subtlety that trips people up: chat.scheduleMessage is one-shot. Slack does not do recurring scheduled messages. If you want a weekly maintenance reminder or a daily summary, you own the recurrence — run a cron (or a scheduled job) that schedules the next instance each cycle. Don’t try to schedule a year of messages up front; schedule the next one each time the current one fires, so changes to cadence take effect immediately.
Keep the cadence honest
The fastest way to get a proactive bot muted is to over-schedule. Every scheduled message should clear a bar: would a human have wanted this ping, at this time, about this thing? Maintenance heads-ups, expiry warnings, handoff nudges — yes. “Good morning team” — no. Audit your scheduled output the same way you’d audit alert rules, and cut anything that’s become wallpaper.
Where to start
Pick the one recurring thing your team forgets — cert rotation, the maintenance heads-up, the on-call handoff — and automate just that with a scheduled message or reminder. Build the /scheduled list command early so you never lose track of what’s pending. For more on building Slack tooling that respects attention, see our Slack for ops guides.
Scheduled messages fire unattended, sometimes days later. Verify timing and make every scheduled post cancelable before relying on it.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.