Cloud Architecture

Building Scalable Messaging Systems with AWS SQS & SNS

Master asynchronous messaging patterns with Amazon SQS and SNS. Learn how to build decoupled, scalable applications using message queues and pub/sub notifications in a comprehensive Next.js demonstration.

15 min read
Published

Complete Tutorial Code

Follow along with the complete source code for this AWS SQS & SNS tutorial. Includes a full messaging demo with Next.js 16 and AWS SDK v3.

View on GitHub

Introduction

Modern applications require robust messaging systems to handle asynchronous communication, decouple components, and scale effectively. Amazon Web Services provides two powerful messaging services: Simple Queue Service (SQS) for message queuing and Simple Notification Service (SNS) for publish-subscribe patterns.

This comprehensive tutorial will guide you through building a complete messaging application using AWS SQS and SNS. We'll explore core concepts, implement real-world patterns, and demonstrate how these services work together to create scalable, resilient architectures.

Understanding AWS Messaging Services

AWS SQS and SNS serve different but complementary purposes in distributed systems. SQS provides reliable message queuing for point-to-point communication, while SNS enables fan-out messaging through publish-subscribe patterns.

SQS - Message Queuing

Producer → Queue → Consumer
One message, one consumer
Work distribution pattern

Reliable message delivery with guaranteed processing

SNS - Pub/Sub Notifications

Publisher → Topic → [ Email Subscriber, SMS Subscriber, HTTP Endpoint, SQS Queue ]

One message delivered to multiple subscribers

Core SQS Concepts

Message Queue Fundamentals

SQS provides a managed message queue service that enables asynchronous communication between distributed application components. Messages are stored reliably until they are processed and deleted by consumers.

// Sending a message to SQS
const params = {
  QueueUrl: process.env.SQS_QUEUE_URL,
  MessageBody: JSON.stringify({
    orderId: '12345',
    customerId: 'user-456',
    items: ['product-1', 'product-2'],
    timestamp: new Date().toISOString()
  }),
  MessageAttributes: {
    'MessageType': {
      DataType: 'String',
      StringValue: 'ORDER_CREATED'
    }
  }
};

const result = await sqsClient.send(new SendMessageCommand(params));

Message Processing Patterns

SQS supports both short polling and long polling for message retrieval. Long polling reduces costs and improves efficiency by waiting for messages to arrive rather than immediately returning empty responses.

// Receiving messages with long polling
const receiveParams = {
  QueueUrl: process.env.SQS_QUEUE_URL,
  MaxNumberOfMessages: 10,
  WaitTimeSeconds: 20, // Long polling
  MessageAttributeNames: ['All']
};

const messages = await sqsClient.send(
  new ReceiveMessageCommand(receiveParams)
);

// Process each message
for (const message of messages.Messages || []) {
  try {
    // Process the message
    await processMessage(JSON.parse(message.Body));
    
    // Delete the message after successful processing
    await sqsClient.send(new DeleteMessageCommand({
      QueueUrl: process.env.SQS_QUEUE_URL,
      ReceiptHandle: message.ReceiptHandle
    }));
  } catch (error) {
    console.error('Message processing failed:', error);
    // Message will become visible again after visibility timeout
  }
}

Core SNS Concepts

Topics and Subscriptions

SNS topics act as communication channels where publishers send messages and subscribers receive them. A single message published to a topic is delivered to all active subscriptions.

// Publishing a message to SNS topic
const publishParams = {
  TopicArn: process.env.SNS_TOPIC_ARN,
  Message: JSON.stringify({
    event: 'USER_REGISTERED',
    userId: 'user-789',
    email: 'user@example.com',
    timestamp: new Date().toISOString()
  }),
  MessageAttributes: {
    'event_type': {
      DataType: 'String',
      StringValue: 'USER_REGISTERED'
    },
    'priority': {
      DataType: 'String',
      StringValue: 'high'
    }
  }
};

const result = await snsClient.send(new PublishCommand(publishParams));

Subscription Management

SNS supports multiple subscription protocols including email, SMS, HTTP/HTTPS endpoints, and SQS queues. This flexibility allows you to integrate with various systems and notification channels.

// Creating subscriptions for different protocols
const subscriptions = [
  {
    Protocol: 'email',
    Endpoint: 'admin@example.com'
  },
  {
    Protocol: 'sqs',
    Endpoint: 'arn:aws:sqs:us-east-1:123456789012:notification-queue'
  },
  {
    Protocol: 'https',
    Endpoint: 'https://api.example.com/webhooks/notifications'
  }
];

for (const subscription of subscriptions) {
  await snsClient.send(new SubscribeCommand({
    TopicArn: process.env.SNS_TOPIC_ARN,
    Protocol: subscription.Protocol,
    Endpoint: subscription.Endpoint
  }));
}

Building the Demo Application

Our demo application showcases practical implementations of both SQS and SNS using Next.js 16 with the App Router. The application demonstrates real-world messaging patterns and best practices for AWS integration.

Application Architecture

The demo follows a modern full-stack architecture with clear separation between frontend components, API routes, and AWS service integrations:

Frontend: Next.js 16 with React components, TypeScript, and Tailwind CSS
API Layer: Next.js API routes handling SQS and SNS operations
AWS Integration: AWS SDK v3 with proper error handling and retry logic
State Management: Custom React hooks for SQS and SNS operations

Setting Up AWS Services

The application requires proper AWS configuration including IAM permissions, SQS queue creation, and SNS topic setup. The repository includes detailed setup instructions:

// AWS SDK v3 Configuration
import { SQSClient } from '@aws-sdk/client-sqs';
import { SNSClient } from '@aws-sdk/client-sns';

const awsConfig = {
  region: process.env.AWS_REGION || 'us-east-1',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
};

export const sqsClient = new SQSClient(awsConfig);
export const snsClient = new SNSClient(awsConfig);

Component Architecture

The application uses a modular component structure with custom hooks for state management and API interactions. This approach provides clean separation of concerns and reusable logic.

// Custom hook for SQS operations
export function useSQS() {
  const [messages, setMessages] = useState<SQSMessage[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const sendMessage = async (messageBody: string) => {
    setLoading(true);
    setError(null);
    
    try {
      const response = await fetch('/api/sqs/send', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ message: messageBody }),
      });
      
      if (!response.ok) throw new Error('Failed to send message');
      
      const result = await response.json();
      return result;
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Unknown error');
      throw err;
    } finally {
      setLoading(false);
    }
  };

  const receiveMessages = async () => {
    // Implementation for receiving messages
  };

  return { messages, loading, error, sendMessage, receiveMessages };
}

Advanced Messaging Patterns

SQS + SNS Integration

Combining SQS and SNS creates powerful messaging architectures. SNS can fan out messages to multiple SQS queues, enabling parallel processing of the same event by different services.

Error Handling and Retry Logic

Proper error handling is crucial for reliable messaging systems. The demo implements comprehensive error handling with exponential backoff and dead letter queue patterns.

Message Filtering and Routing

SNS message filtering allows subscribers to receive only relevant messages based on message attributes. This reduces processing overhead and improves system efficiency.

Key Benefits of AWS Messaging

Scalability

Automatically scales to handle millions of messages with consistent performance.

Reliability

Guaranteed message delivery with built-in redundancy and durability.

Decoupling

Loose coupling between components enables independent scaling and deployment.

Cost Effective

Pay-per-use pricing model with no upfront costs or minimum fees.

Getting Started

Ready to build scalable messaging systems with AWS? Follow these steps to get the tutorial project running on your local machine:

  1. 1
    Clone the repository:
    git clone https://github.com/audoir/sqs-sns-tutorial.git
  2. 2
    Install dependencies:
    npm install
  3. 3
    Configure AWS services:
    Follow AWS_SETUP.md for detailed instructions
  4. 4
    Set up environment variables:
    Copy .env.example to .env.local and configure
  5. 5
    Start the development server:
    npm run dev
  6. 6
    Explore the application:
    http://localhost:3000 - Interactive messaging demo

Learning Outcomes

By completing this tutorial, you will have gained hands-on experience with:

  • • Setting up and configuring AWS SQS queues and SNS topics
  • • Implementing message sending and receiving with proper error handling
  • • Building publish-subscribe patterns with SNS subscriptions
  • • Integrating AWS SDK v3 with Next.js applications
  • • Managing AWS credentials and IAM permissions securely
  • • Implementing custom React hooks for AWS service interactions
  • • Understanding message queuing and pub/sub architectural patterns
  • • Best practices for scalable, decoupled application design

Conclusion

AWS SQS and SNS provide the foundation for building scalable, resilient messaging systems. By decoupling application components and enabling asynchronous communication, these services help create applications that can handle varying loads and recover gracefully from failures.

The demo application demonstrates practical implementation patterns that you can adapt for your own projects. From simple message queuing to complex event-driven architectures, these concepts form the backbone of modern cloud-native applications.

About the Author

Wayne Cheng is the founder and AI app developer at Audoir, LLC. Prior to founding Audoir, he worked as a hardware design engineer for Silicon Valley startups and an audio engineer for creative organizations. He holds an MSEE from UC Davis and a Music Technology degree from Foothill College.

Further Exploration

To continue your AWS messaging journey, explore the complete tutorial repository and experiment with advanced features like dead letter queues, message filtering, and Lambda integration. Consider implementing cross-service communication patterns to deepen your understanding of event-driven architectures.

For more AI-powered development tools and tutorials, visit Audoir .