Sending SMS with AWS SNS in NestJS: A Developer Guide - code-examples -

Frequently Asked Questions

Integrate AWS SNS into your NestJS application. This involves setting up your project with the necessary AWS SDK, configuring your environment variables, creating an AWS IAM user with SNS permissions, implementing an SMS service in NestJS to handle the sending logic, and exposing this service via a controller with a REST API endpoint. This setup will enable your NestJS backend to send SMS messages programmatically.
AWS SNS (Simple Notification Service) is used as the messaging service to deliver SMS messages directly to phone numbers. It is chosen for its direct SMS sending capability, scalability, reliability, and integration with the AWS ecosystem. SNS handles the complexities of telephony infrastructure, allowing developers to focus on application logic.
NestJS provides a structured and efficient way to build server-side applications. Its modular architecture, dependency injection, and TypeScript support make it easier to manage dependencies, test code, and maintain the application, especially when integrating with external services like AWS SNS.
Create an IAM user in your AWS account and grant it permissions to use SNS, at least the "sns:Publish" action. Generate an access key ID and secret access key for this user. Store these credentials securely, preferably not directly in files, and load them into your NestJS application using environment variables or a more secure method like AWS Secrets Manager for production.
Not all AWS regions support SMS sending. Choose a region like us-east-1 (N. Virginia), us-west-2 (Oregon), or others listed in the AWS documentation for SNS supported regions. Ensure the region you select in your AWS configuration matches the region your SNS service is configured for.
Implement error handling within your NestJS SMS service using try-catch blocks to capture errors during SNS interactions. Throw a custom exception such as `AwsServiceUnavailableException` to provide more specific HTTP responses, for example a 503 status code for service unavailability. Log the errors for debugging and monitoring.
Use a data transfer object (DTO) and class-validator. Create a DTO (e.g., `SendSmsDto`) for the API request and use decorators like `@IsString`, `@IsNotEmpty`, and `@Matches` with a regular expression for E.164 phone number format validation in the DTO class. Enable a global validation pipe in your NestJS application (`main.ts`) to automatically validate incoming requests against the DTO. This will reject invalid phone number formats with 400 Bad Request errors.
The `AWS.SNS.SMS.SMSType` attribute determines how AWS SNS handles SMS delivery. Setting it to 'Transactional' makes messages suitable for critical alerts and OTPs (One-Time Passwords) because they have higher priority and are more likely to bypass DND. 'Promotional' is more cost-effective for marketing messages.
Avoid storing AWS credentials directly in files. For production, use IAM roles for EC2, ECS, or Lambda. This automatically handles credentials. You can also utilize AWS Secrets Manager or Parameter Store to store credentials and retrieve them during runtime within your NestJS application.
Implement rate limiting using the `@nestjs/throttler` module. Configure it globally or per route to restrict the number of requests per IP within a time window (e.g., 10 requests per 60 seconds). This helps prevent excessive usage, denial-of-service attacks, and keeps costs under control.
Mock the `SNSClient` from the AWS SDK to avoid actual calls to AWS during testing. Utilize a mocking library like `aws-sdk-client-mock` to simulate successful and failed responses from SNS. This enables isolated testing of the SMS service logic. Mock the `ConfigService` to provide test values for AWS credentials and region without accessing environment variables.
Install `@nestjs/throttler`. Add `ThrottlerModule` to your imports and configure limits (e.g., `ttl: 60000`, `limit: 10` for 10 requests every 60 seconds). Include `ThrottlerGuard` as a global guard to enforce the rate limits. You can apply this at the global level or just for specific controllers.
Use 'Transactional' for critical messages like one-time passwords (OTPs) and alerts where high deliverability is essential. 'Promotional' is better for marketing messages where cost is a primary concern. Remember transactional messages might bypass DND registries but are more expensive.