Your phone as a pager, for free: push, ntfy, or Slack?

Butters can send a notified event as a native push, to an ntfy topic, or to a Slack or Discord channel, all at once. Here is how the three differ, and which one to use for whom.

6 min read
A blue phone connected by lines to a yellow bell, a coral chat bubble and a blue megaphone

Butters can put a notified event in three places: a browser or phone notification, an ntfy topic, or a Slack or Discord channel. You don't have to pick one. But they behave differently, and knowing how helps you decide who gets what.

This post compares the three. If you haven't set up notify yet, start with Get pinged for the right events, and only those , which covers the flag and a rule for when to use it. For setting up webhooks and push, see Send events in, send them out .

They all fire at once

Here's how it works. When an event arrives with notify: true, Butters sends it to every enabled destination on the project in parallel: every ntfy topic, every outgoing webhook, and every device with push turned on. There's no routing and no per-destination filter. Every notified event goes to every enabled destination.

So picking a channel isn't about sorting events into buckets. It's about who should hear it and how loudly. If you need different events to reach different people, put them in different projects.

Web push: for you, on your own devices

Web push is the newest option and needs the least setup. Open a project's Settings, click Enable on this device, accept the browser prompt, and you're done. There's no app to install and no third-party account.

What to know:

  • It's per project and per device. You turn it on separately for each project and each browser or phone. Your laptop and phone are two separate subscriptions.
  • It's personal. Only you see and manage your own devices. A teammate who wants notifications turns them on for themselves, and when someone leaves the organization, their devices stop getting pushes straight away.
  • iPhone and iPad need the Home Screen. Safari only allows push for web apps added to the Home Screen, on iOS 16.4 or later.
  • Butters sends once and the push service does the rest. Butters makes one attempt per device. The browser's push service (Apple, Google or Mozilla) then holds the message for up to 24 hours, so it still arrives if your phone was offline for a while.

The main limit is that you can't set a volume for push. There's no priority setting, so every push arrives as a normal notification, and how loud it is depends on your phone's settings for your browser or the Home Screen app.

It costs nothing. There's no fee to Butters or to the push services.

ntfy: when you need to control the volume

ntfy is the one to use when you want to decide how insistent an alert is, or you want to run the whole thing yourself.

  • Priority is set per destination, from 1 to 5, and it's the only one of the three channels with a volume knob. A priority 5 topic for production failures and a priority 2 topic for "look at this today" can live on different projects.
  • You can host it yourself. Point a destination at your own ntfy server, with a token or username and password if the server needs one.
  • On the public server, the topic name is the password. Anyone who guesses it can read your alerts, so make it long and random.
  • Butters sends each event once. If your ntfy server is down or slow to answer (the timeout is 5 seconds), that notification is missed and the error shows on the destination in Settings. There's no retry.

On cost: the public ntfy.sh server is free to use, within its rate limits, and ntfy is open source if you'd rather host it. The phone apps are free too.

The earlier post covers connecting a destination step by step .

Slack and Discord: for the team

Outgoing webhooks send notified events to a Slack or Discord channel, or to your own endpoint as signed JSON. This is the channel to use when the whole team should see the alert, and when "who's handling this?" should be answered in a thread.

  • Everyone in the channel sees it. Nobody has to opt in on their own devices, and new team members get the history just by joining the channel.
  • Failures are retried, briefly. A delivery gets up to 3 attempts over a few seconds, for timeouts, network errors, 429s and 5xxs.
  • The retries are all you get. They happen in memory. If the Butters server restarts partway through, that delivery is lost, and the destination's row in Settings is the only record.

Use the Test button on each destination when you add it, before a real alert fails silently.

Incoming webhooks in Slack and Discord work on their free plans, although Slack's free plan limits how far back message history goes. For an alert channel, that rarely matters.

Mixing them

Since everything fires in parallel, the useful setups combine channels. Three that work well:

Push for you, Slack for the team. You get a buzz on your phone; the channel keeps a shared record and gives others a place to reply. This is a good default for a team of two to ten.

ntfy at priority 5 for the pager, Discord for context. Whoever's on call subscribes to a loud ntfy topic. Everyone else follows the Discord channel at their own pace.

Two projects for two volumes. Put critical events (failed deploys, crashed processes, failed payment retries) in a project with a priority 5 ntfy topic and push turned on. Put "today, not at 2am" events in a second project that only has a Slack destination. A notification's volume then depends on where the event is sent, which you decide in code.

The rule

Pick each channel for who it reaches, not for what it can do. Use push for the person who has to act. Use ntfy when volume or self-hosting matters. Use Slack or Discord when the team should see it too.

Start with one of each at most. If a channel only ever repeats what another one already told the same person, remove it. A notification someone has already seen elsewhere is just noise.