Setting Up Triggered Notifications: Email, SMS, Telegram

Introduction

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1284
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1240
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1031
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1104
  • image_website-_0.webp
    Website development for Red Pear
    553

Introduction

Imagine a customer placing an order on your site, paying by card, but not receiving a status update. They start worrying, call support — your business loses money and reputation. How do you build a fault-tolerant notification system that delivers messages via email, SMS, or Telegram regardless of channel failures? We break down the architecture, code, and infrastructure tested on over 50 projects in e-commerce, fintech, and SaaS. We guarantee that no event is lost — our system uses a queue with exponential backoff and monitoring.

In over 5 years, we have never encountered a lost notification due to an architectural mistake. All issues were resolved during the design phase.

Problems We Solve

  • Message loss — a channel goes down or the API returns an error (e.g., Twilio returns 500). We use a queue (Bull Queue) with retry and logging. On failure, the message is retried after 2, 4, 8 seconds (exponential backoff). After 3 failures, it goes into a Dead Letter Queue for manual analysis.
  • Channel confusion — a user wants Telegram notifications but gets SMS. We implement a personal cabinet with preference settings: channel selection for each event type, quiet hours, and time zone.
  • Spam traps — transactional and marketing notifications are separated. Marketing uses separate channels (email) with an unsubscribe option. Quiet hours (22:00–08:00) block sending during off-hours.
Expand sample code for Notification Service
// notification.service.ts interface NotificationRequest { userId: string; type: NotificationType; data: Record<string, unknown>; channels?: Channel[]; priority?: 'high' | 'normal' | 'low'; } type NotificationType = | 'order.placed' | 'order.shipped' | 'payment.failed' | 'password.reset' | 'promo.discount'; class NotificationService { async send(request: NotificationRequest): Promise<void> { const prefs = await this.userPrefsRepo.findByUserId(request.userId); const channels = request.channels ?? this.resolveChannels(request.type, prefs); await Promise.allSettled( channels.map(channel => this.sendViaChannel(channel, request, prefs)) ); } private resolveChannels(type: NotificationType, prefs: UserPrefs): Channel[] { const channelMap: Record<NotificationType, Channel[]> = { 'order.placed': ['email', 'telegram'], 'order.shipped': ['email', 'sms', 'telegram'], 'payment.failed': ['email', 'sms'], 'password.reset': ['email'], 'promo.discount': prefs.marketingChannels }; return channelMap[type] ?? ['email']; } } 

Email via Resend

For email notifications, we use Resend. Below is a code example:

import { Resend } from 'resend'; const resend = new Resend(process.env.RESEND_API_KEY); async function sendEmailNotification( user: User, type: NotificationType, data: Record<string, unknown> ) { const template = emailTemplates[type]; await resend.emails.send({ from: '[email protected]', to: user.email, subject: template.subject(data), react: template.component({ user, ...data }) }); } // Template for order.shipped const orderShippedTemplate = { subject: (data) => `Your order #${data.orderId} has shipped`, component: ({ user, orderId, trackingNumber, estimatedDelivery }) => ( <OrderShippedEmail name={user.firstName} orderId={orderId} trackingNumber={trackingNumber} trackingUrl={`https://example.com/track/${trackingNumber}`} estimatedDelivery={estimatedDelivery} /> ) }; 

SMS via Twilio

For SMS notifications, we use Twilio. Example:

import twilio from 'twilio'; const client = twilio(process.env.TWILIO_SID, process.env.TWILIO_TOKEN); async function sendSmsNotification( user: User, type: NotificationType, data: Record<string, unknown> ) { if (!user.phone || !user.phoneVerified) return; const templates: Record<NotificationType, (data: Record<string, unknown>) => string> = { 'order.shipped': (d) => `Order #${d.orderId} shipped. Track: ${d.trackingNumber}. Expected by ${d.date}`, 'payment.failed': (d) => `Payment for order #${d.orderId} failed. Update your card: ${d.retryUrl}` }; const text = templates[type]?.(data); if (!text) return; await client.messages.create({ to: user.phone, from: process.env.TWILIO_PHONE, body: text }); } 

Telegram via Bot API

For Telegram notifications, we use a Telegram bot. Example:

import TelegramBot from 'node-telegram-bot-api'; const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN); async function sendTelegramNotification( user: User, type: NotificationType, data: Record<string, unknown> ) { if (!user.telegramChatId) return; const messages: Record<string, (d: Record<string, unknown>) => string> = { 'order.shipped': (d) => `📦 *Order #${d.orderId} shipped*\n\nTracking: \`${d.trackingNumber}\`\nExpected delivery: ${d.date}`, 'payment.failed': (d) => `⚠️ *Payment failed*\n\nOrder #${d.orderId} not paid. [Retry payment](${d.retryUrl})` }; const text = messages[type]?.(data); if (!text) return; await bot.sendMessage(user.telegramChatId, text, { parse_mode: 'Markdown', disable_web_page_preview: true }); } // User linking Telegram account bot.onText(/\/start (.+)/, async (msg, match) => { const linkToken = match[1]; const userId = await verifyLinkToken(linkToken); if (userId) { await userRepo.updateTelegramChatId(userId, msg.chat.id.toString()); bot.sendMessage(msg.chat.id, '✅ Telegram connected successfully! You will receive notifications.'); } }); 

Preference Management

// Table user_notification_prefs interface UserNotificationPrefs { userId: string; emailEnabled: boolean; smsEnabled: boolean; telegramEnabled: boolean; marketingEmailEnabled: boolean; marketingSmsEnabled: boolean; quietHoursStart: string; quietHoursEnd: string; timezone: string; } 

How to Prevent Notification Loss?

A notification queue with retry is the key element. On send failure (e.g., Twilio returns 500), the message retries after 2, 4, 8 seconds. After 3 failures, it goes into the DLQ (dead letter queue) for manual analysis. Delivery reliability without a queue is about 95%; with a queue, it's 99.9%. That's 50 times fewer lost messages. For example, with 10,000 notifications per day, without a queue you lose 500; with a queue, only 10.

Why Do You Need a Queue with Retry?

Services are unstable: Resend may delay emails, Telegram has rate limits. A queue with backoff guarantees the message will be delivered without a crunch. We use Bull Queue with Redis. Additionally, we set up monitoring: if the error count exceeds a threshold, we send an alert to the team in Telegram.

Channel Comparison

Channel Delivery Speed Reliability Ideal For Cost per Unit
Email minutes high marketing, transactional $0.001 per email (Resend)
SMS seconds high urgent events (payment) $0.05 per message (Twilio)
Telegram instant medium push notifications free

SMS is delivered 60 times faster than email, which is critical for payment notifications. Although the per-unit cost of SMS is higher, it's justified for urgent events.

How to Set Up Notifications: Step-by-Step Guide for Notification Setup

  1. Define triggers. Which events in your app require notifications? Typical set: order placed, payment failed, password reset.
  2. Choose channels. For each trigger, determine the preferred channel. Duplicate critical events to two channels (email + SMS).
  3. Set up the notification queue. Integrate Bull Queue with Redis to process messages with retry and logging.
  4. Create templates. Develop HTML templates for email, text templates for SMS and Telegram with personalization.
  5. Test scenarios. Test each channel failure, rate limit exceeding, and correct error handling.

Process

Stage Duration Result
Analysis 1–2 days Flow diagram and triggers
Design 2–3 days Architecture and channel selection
Implementation 5–7 days Integration and code
Testing 2 days Test report
Deployment 1 day Working system

What's Included

  • Notification architecture design
  • Integration for email (Resend/SendGrid), SMS (Twilio), and Telegram (Bot API)
  • Queue and retry configuration
  • Personal cabinet for preference management
  • Scenario testing (load, channel failures)
  • Documentation and team training

Timeline

Basic configuration (3 channels, 5 triggers, notification queue) — from 1 to 2 weeks. The timeline depends on business logic complexity. Contact us — we'll assess your project in 1 day. Get a consultation — we'll select the optimal channels for your business and traffic.

Notification Costs

We use providers with low rates: Resend from $0.001 per email, Twilio from $0.05 per SMS. Telegram is free. You only pay for actual usage, with no hidden fees. Optimizing channel selection can save up to 40% of your notification budget. For example, sending 10,000 transactional emails costs $10, while 10,000 SMS costs $500; switching to Telegram for non-urgent notifications can save thousands annually.