Real World Example

Notification Service at a Fintech

Apps like Paytm and CRED send OTPs and alerts via SMS, email and push. One NotificationsService hides the channels from the rest of the app, and each channel is its own provider.

src/notifications/notifications.service.ts

import { Injectable, Logger } from '@nestjs/common';
import { SmsSender } from './channels/sms.sender';
import { EmailSender } from './channels/email.sender';
import { PushSender } from './channels/push.sender';

@Injectable()
export class NotificationsService {
  private readonly logger = new Logger(NotificationsService.name);

  constructor(
    private readonly sms: SmsSender,
    private readonly email: EmailSender,
    private readonly push: PushSender,
  ) {}

  async paymentReceived(user: { phone: string; email: string; deviceToken?: string }, amount: number) {
    const text = `₹${amount} received in your wallet`;
    await Promise.all([
      this.sms.send(user.phone, text),
      this.email.send(user.email, 'Payment received', text),
      user.deviceToken ? this.push.send(user.deviceToken, text) : Promise.resolve(),
    ]);
    this.logger.log(`payment alert sent to ${user.phone}`);
  }
}

Tip: Because channels are injected, a unit test can pass fake senders and check what was sent, without sending a real SMS.