Channel Overview
All 24 drivers at a glance — pricing, free tiers, and when to use each.
go-notification ships with seven channel families. Every family has multiple driver choices so you can match cost, deliverability, and compliance needs.
Quick Comparison
| Channel | Drivers | Free Options | Paid Options | Best For |
|---|---|---|---|---|
| 7 | SMTP, Mailgun (100/day), SES (3k/mo) | SendGrid, Postmark | Transactional email | |
| 5 | WAHA Core (self-hosted) | Fonnte, Twilio, Meta | Customer comms (ID) | |
| SMS | 4 | Twilio trial, SNS (100/mo) | Twilio, Zenziva | OTP, alerts |
| Chat | 5 | All free | — | Internal team notifs |
| Push | 1 | FCM (unlimited) | — | Mobile app notifs |
| Database | 1 | Built-in | — | In-app notifications |
| Webhook | 1 | Built-in | — | Custom integrations |
By family
Email (7 drivers)
SMTP, Mailgun, SendGrid, AWS SES, Resend, Postmark, Mailtrap. Start with the Email Overview for driver comparison and cloud port-blocking warnings.
WhatsApp (5 drivers)
WAHA, Fonnte, Wablas, Twilio WhatsApp, Meta Cloud API. See the WhatsApp Overview for official vs. unofficial API tradeoffs.
SMS (4 drivers)
Twilio, Zenziva, Vonage (Nexmo), AWS SNS.
Chat (5 drivers)
Slack, Telegram, Discord, Microsoft Teams.
Push (1 driver)
Firebase Cloud Messaging (FCM) — iOS, Android, and Web.
Database (1 driver — 3 backends)
Database channel — in-app notifications stored in Postgres, MySQL, or SQLite.
Webhook (1 driver)
Generic HTTP POST for any custom integration.
Registering channels
A channel is registered by its driver. The name it reports from Name() is the string you use in Notification.Via and RouteNotificationFor. Defaults per family:
| Family | Default Name() |
|---|---|
"mail" | |
| SMS | "sms" |
| Chat (Slack, Telegram, Discord, Teams) | "chat" |
"whatsapp" | |
| Push | "push" |
| Webhook | "webhook" |
| Database | "database" |
notifier.RegisterChannel(mailgun.New(mailgun.Config{ /* ... */ }))
// registered as "mail" → Via returns []string{"mail"}Multiple instances of one driver
Silent overwrite if Config.Name is empty
RegisterChannel keys by the driver's Name(). Two drivers reporting the
same name silently overwrite — the second wins, no error, no warning.
The trap: Slack, Telegram, Discord, and Teams all default to "chat".
Registering more than one without setting Config.Name means only the last
one is reachable. The same applies to two mail drivers (both "mail"),
two SMS drivers ("sms"), etc. Always set a distinct Config.Name when
registering more than one driver from the same family.
To run more than one instance of a family — transactional vs. marketing mail, or Slack and Telegram — give each a distinct name via its Config.Name field:
notifier.RegisterChannel(mailgun.New(mailgun.Config{Name: "mail_tx", /* ... */}))
notifier.RegisterChannel(sendgrid.New(sendgrid.Config{Name: "mail_mk", /* ... */}))
notifier.RegisterChannel(slack.New(slack.Config{Name: "slack", /* ... */}))
notifier.RegisterChannel(telegram.New(telegram.Config{Name: "telegram", /* ... */}))Then reference those names everywhere:
func (n Promo) Via(notification.Notifiable) []string { return []string{"mail_mk", "slack"} }
func (u User) RouteNotificationFor(channel string) string {
switch channel {
case "mail_tx", "mail_mk": return u.Email
case "slack": return u.SlackWebhook
case "telegram": return u.TelegramChatID
}
return ""
}Decision guides
Picking the right provider matters more than the code you write around it. Dedicated guides:
- Choosing an Email Driver — flowchart + pricing at scale.
- Choosing a WhatsApp Driver — ban risk, official vs. unofficial, Indonesia-specific options.
- SMTP Port Blocking on Cloud — why SMTP silently fails on GCP/AWS/DigitalOcean.