Skip to main content

Multi-Channel Notification System

Overview

The Multi-Channel Notification System is a comprehensive solution for delivering notifications across multiple communication channels (Email, SMS, WhatsApp, Telegram, and FCM). It provides a unified interface for sending notifications while respecting user preferences, Do Not Disturb (DND) settings, and notification categories.

Core Features

Multiple Delivery Channels

  • Email: Default channel using Spring Mail
  • SMS: Twilio integration for SMS delivery
  • WhatsApp: WhatsApp Business API integration
  • Telegram: Telegram Bot API integration
  • Firebase Cloud Messaging (FCM): Push notifications for mobile devices

Notification Categories

  • BILLING: Payment and subscription-related notifications
  • SECURITY: Password changes, security alerts
  • SUPPORT: Support ticket updates
  • PROMOTIONAL: Marketing and special offers
  • SYSTEM: System maintenance and updates
  • ACCOUNT: Account-related changes
  • SUBSCRIPTION: Subscription status updates

User Preferences Management

  • Per-channel enable/disable settings
  • Category-based filtering
  • DND (Do Not Disturb) scheduling
  • Timezone-aware delivery
  • Localization support

System Architecture

graph TD
A[Client Application] --> B[GraphQL API Layer]
B --> C[MultiChannelNotificationService]
C --> D[Channel Services]
D --> E[EmailService]
D --> F[SmsService]
D --> G[WhatsAppService]
D --> H[TelegramService]
D --> I[FCMService]
J[NotificationPreferences] --> C
K[MessageTemplates] --> C
L[RateLimiter] --> C

GraphQL API Reference

Notification Preferences

Get User Preferences

query GetNotificationPreferences {
getNotificationPreferences {
enabledChannels
enabledCategories
dndEnabled
dndStartTime
dndEndTime
timezone
}
}

Update Preferences

mutation UpdateNotificationPreferences($input: NotificationPreferencesInput!) {
updateNotificationPreferences(input: $input) {
enabledChannels
enabledCategories
dndEnabled
dndStartTime
dndEndTime
timezone
}
}

input NotificationPreferencesInput {
enabledChannels: [NotificationChannel!]!
enabledCategories: [NotificationCategory!]!
dndEnabled: Boolean
dndStartTime: String
dndEndTime: String
timezone: String
}

Channel-Specific Operations

Send WhatsApp Notification

mutation SendWhatsAppNotification(
$userId: Int
$username: String
$message: String!
) {
sendWhatsAppNotification(
userId: $userId
username: $username
message: $message
)
}

Send Telegram Notification

mutation SendTelegramNotification(
$userId: Int
$username: String
$message: String!
) {
sendTelegramNotification(
userId: $userId
username: $username
message: $message
)
}

Send FCM Notification

mutation SendNotificationByToken(
$token: String!
$notification: NotificationInput!
) {
sendNotificationByToken(token: $token, notification: $notification) {
status
message
}
}

input NotificationInput {
subject: String!
content: String!
}

Administrative Operations

Get Notification Stats

query GetNotificationStats {
getNotificationStats {
totalNotificationsSent
notificationsByChannel {
channel
count
successRate
}
notificationsByCategory {
category
count
}
failedNotifications
}
}

Implementation Examples

Sending Multi-Channel Notification

// Using MultiChannelNotificationService
public void sendNotification(
User user,
String messageKey,
NotificationCategory category,
Map<String, Object> variables,
Function<NotificationMessage, String> messageProvider) {

NotificationPreferences prefs = getPreferences(user);
UserProfile profile = user.getProfile();

if (!prefs.isCategoryEnabled(category) || prefs.isDndActive()) {
log.debug("Notification skipped - Category disabled or DND active");
return;
}

for (NotificationChannel channel : prefs.getEnabledChannels()) {
try {
NotificationMessage message = new NotificationMessage(channel, variables);
String content = messageProvider.apply(message);
sendToChannel(channel, user, profile, content, messageKey, variables);
} catch (Exception e) {
log.error("Failed to send notification through channel {}", channel, e);
}
}
}

Channel-Specific Implementation

FCM Service

public FcmNotificationDto sendNotification(NotificationDto notificationDto, String token) {
Message message = Message.builder()
.setToken(token)
.setNotification(Notification.builder()
.setTitle(notificationDto.getSubject())
.setBody(notificationDto.getContent())
.build())
.putAllData(convertToStringData(notificationDto.getData()))
.setAndroidConfig(getAndroidConfig())
.setApnsConfig(getApnsConfig(notificationDto))
.build();

try {
String response = firebaseMessaging.sendAsync(message).get();
return new FcmNotificationDto();
} catch (Exception e) {
return new FcmNotificationDto("Failed to send FCM notification: " + e.getMessage());
}
}

Rate Limiting

The system implements rate limiting using token bucket algorithm:

public class MessageRateLimiter {
private final Map<String, Bucket> whatsappBuckets = new ConcurrentHashMap<>();
private final Map<String, Bucket> telegramBuckets = new ConcurrentHashMap<>();

public boolean tryConsumeWhatsApp(String phoneNumber) {
Bucket bucket = whatsappBuckets.computeIfAbsent(phoneNumber,
k -> createBucket(config.getWhatsapp()));
return bucket.tryConsume(1);
}

public boolean tryConsumeTelegram(String chatId) {
Bucket bucket = telegramBuckets.computeIfAbsent(chatId,
k -> createBucket(config.getTelegram()));
return bucket.tryConsume(1);
}
}

Error Handling

Common error scenarios and their handling:

Error TypeDescriptionHandling Strategy
Channel UnavailableCommunication channel is downRetry with exponential backoff
Rate LimitedToo many requestsWait for rate limit reset
Invalid RecipientInvalid phone/email/tokenLog error and skip delivery
Template ErrorMessage template issuesFall back to default template
DND ViolationMessage during DND periodQueue for later delivery

Best Practices

  1. Template Management

    • Use language-specific message templates
    • Support HTML and plain text formats
    • Include fallback templates
    • Validate template variables
  2. Error Handling

    • Implement retry mechanisms
    • Log delivery failures
    • Monitor error rates
    • Provide fallback channels
  3. Performance

    • Use async operations
    • Implement caching
    • Batch similar notifications
    • Queue non-urgent messages
  4. Security

    • Validate input data
    • Rate limit per user/channel
    • Encrypt sensitive data
    • Audit notification delivery

Configuration

The system can be configured through application.yml:

messaging:
telegram:
bot-token: "your-bot-token"
bot-username: "your-bot-username"
admin-group-id: "admin-group-id"

whatsapp:
connection:
retry-attempts: 3
retry-delay: 5000
timeout: 30000

templates:
location: "classpath:templates/messages"
cache-ttl: 3600

tracking:
enabled: true
retention-days: 30
cleanup-interval: 86400

queue:
max-size: 10000
worker-threads: 5
batch-size: 100
process-interval: 60000

Monitoring and Statistics

Key metrics to monitor:

  • Delivery success rate per channel
  • Error rates and types
  • Template rendering performance
  • Queue sizes and processing times
  • Rate limit utilization
  • User preference patterns

Troubleshooting Guide

Common Issues

  1. Messages Not Delivered

    • Check channel status
    • Verify recipient details
    • Check rate limits
    • Review DND settings
  2. Template Issues

    • Validate template syntax
    • Check variable mapping
    • Verify locale settings
    • Review template cache
  3. Performance Problems

    • Monitor queue size
    • Check worker thread status
    • Review batch processing
    • Analyze rate limiting impact

Future Enhancements

Planned improvements:

  1. Additional Channels

    • Slack integration
    • Discord support
    • Microsoft Teams connection
    • Web push notifications
  2. Enhanced Features

    • Message scheduling
    • Rich media support
    • Interactive templates
    • Advanced analytics
  3. Performance Optimizations

    • Improved caching
    • Better batching
    • Smarter rate limiting
    • Enhanced monitoring