or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

client-configuration.mddata-protection.mdindex.mdmessage-publishing.mdpagination.mdpermission-management.mdplatform-applications.mdresource-tagging.mdsms-management.mdsubscription-management.mdtopic-management.md
tile.json

message-publishing.mddocs/

Message Publishing

SNS message publishing enables delivery of messages to topics and direct endpoints with support for various protocols, message attributes, batch operations, and FIFO ordering.

Capabilities

Publish Message

Publishes a message to a topic, direct endpoint, or phone number with comprehensive formatting and attribute support.

/**
 * Publishes a message to an Amazon SNS topic, direct endpoint, or phone number
 * Supports various protocols and message formatting options
 */
class PublishCommand {
  constructor(input: PublishInput);
}

interface PublishInput {
  /** ARN of the topic to publish to */
  TopicArn?: string | undefined;
  /** ARN of the target endpoint or mobile platform endpoint */
  TargetArn?: string | undefined;
  /** Phone number for direct SMS delivery */
  PhoneNumber?: string | undefined;
  /** The message content to send (required) */
  Message: string | undefined;
  /** Subject line for email protocols */
  Subject?: string | undefined;
  /** Message structure format ("json" for platform-specific formatting) */
  MessageStructure?: string | undefined;
  /** Custom message attributes */
  MessageAttributes?: Record<string, MessageAttributeValue> | undefined;
  /** Message group ID for FIFO topics */
  MessageGroupId?: string | undefined;
  /** Message deduplication ID for FIFO topics */
  MessageDeduplicationId?: string | undefined;
}

interface PublishResponse {
  /** Unique identifier assigned to the published message */
  MessageId?: string;
  /** Sequence number for FIFO topics */
  SequenceNumber?: string;
}

type MessageAttributeMap = Record<string, MessageAttributeValue>;

interface MessageAttributeValue {
  /** Data type of the attribute ("String", "Number", "Binary", or custom type) */
  DataType: string;
  /** String value for String and Number data types */
  StringValue?: string;
  /** Binary data for Binary data type */
  BinaryValue?: Uint8Array;
  /** List of string values for String.Array data type */
  StringListValues?: string[];
  /** List of binary values for Binary.Array data type */
  BinaryListValues?: Uint8Array[];
}

Basic Usage Examples:

import { SNSClient, PublishCommand } from "@aws-sdk/client-sns";

const client = new SNSClient({ region: "us-east-1" });

// Publish to topic
const result = await client.send(new PublishCommand({
  TopicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
  Message: "Hello from SNS!",
  Subject: "Test Message"
}));

// Publish SMS directly to phone number
const smsResult = await client.send(new PublishCommand({
  PhoneNumber: "+1234567890",
  Message: "Your verification code is 123456"
}));

// Publish to mobile platform endpoint
const pushResult = await client.send(new PublishCommand({
  TargetArn: "arn:aws:sns:us-east-1:123456789012:endpoint/APNS/MyApp/device-token",
  Message: JSON.stringify({
    APNS: JSON.stringify({
      aps: {
        alert: "New message available",
        badge: 1,
        sound: "default"
      }
    })
  }),
  MessageStructure: "json"
}));

Message Attributes Example:

const result = await client.send(new PublishCommand({
  TopicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
  Message: "Order processed successfully",
  MessageAttributes: {
    orderId: {
      DataType: "String",
      StringValue: "ORDER-12345"
    },
    priority: {
      DataType: "Number",
      StringValue: "1"
    },
    orderTotal: {
      DataType: "Number.currency",
      StringValue: "99.99"
    },
    customerData: {
      DataType: "Binary",
      BinaryValue: new Uint8Array([1, 2, 3, 4])
    },
    tags: {
      DataType: "String.Array",
      StringListValues: ["urgent", "vip", "express"]
    }
  }
}));

FIFO Topic Publishing:

const fifoResult = await client.send(new PublishCommand({
  TopicArn: "arn:aws:sns:us-east-1:123456789012:OrderProcessing.fifo",
  Message: "New order received",
  MessageGroupId: "order-processing",
  MessageDeduplicationId: `order-${Date.now()}`,
  MessageAttributes: {
    orderId: {
      DataType: "String", 
      StringValue: "ORDER-67890"
    }
  }
}));

Publish Batch

Publishes multiple messages in a single request for improved performance and reduced API calls.

/**
 * Publishes up to 10 messages to an Amazon SNS topic in a single request
 * Provides improved throughput and reduced costs for bulk messaging
 */
class PublishBatchCommand {
  constructor(input: PublishBatchInput);
}

interface PublishBatchInput {
  /** ARN of the topic to publish to */
  TopicArn: string;
  /** List of messages to publish (maximum 10) */
  PublishRequestEntries: PublishBatchRequestEntry[];
}

interface PublishBatchRequestEntry {
  /** Unique identifier for this message within the batch */
  Id: string;
  /** The message content */
  Message: string;
  /** Subject line for email protocols */
  Subject?: string;
  /** Message structure format */
  MessageStructure?: string;
  /** Message attributes */
  MessageAttributes?: MessageAttributeMap;
  /** Message group ID for FIFO topics */
  MessageGroupId?: string;
  /** Message deduplication ID for FIFO topics */
  MessageDeduplicationId?: string;
}

interface PublishBatchResponse {
  /** Successfully published messages */
  Successful?: PublishBatchResultEntry[];
  /** Failed message entries */
  Failed?: BatchResultErrorEntry[];
}

interface PublishBatchResultEntry {
  /** ID of the successfully published message */
  Id?: string;
  /** Unique message identifier assigned by SNS */
  MessageId?: string;
  /** Sequence number for FIFO topics */
  SequenceNumber?: string;
}

interface BatchResultErrorEntry {
  /** ID of the failed message */
  Id?: string;
  /** Error code */
  Code?: string;
  /** Error message */
  Message?: string;
  /** Whether the error is sender's fault */
  SenderFault?: boolean;
}

Batch Publishing Examples:

const batchResult = await client.send(new PublishBatchCommand({
  TopicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
  PublishRequestEntries: [
    {
      Id: "msg1",
      Message: "First message",
      Subject: "Message 1",
      MessageAttributes: {
        priority: {
          DataType: "Number",
          StringValue: "1"
        }
      }
    },
    {
      Id: "msg2", 
      Message: "Second message",
      Subject: "Message 2",
      MessageAttributes: {
        priority: {
          DataType: "Number", 
          StringValue: "2"
        }
      }
    },
    {
      Id: "msg3",
      Message: "Third message",
      Subject: "Message 3"
    }
  ]
}));

// Process results
batchResult.Successful?.forEach(success => {
  console.log(`Message ${success.Id} published with ID: ${success.MessageId}`);
});

batchResult.Failed?.forEach(failure => {
  console.log(`Message ${failure.Id} failed: ${failure.Message}`);
});

FIFO Batch Publishing:

const fifoBatch = await client.send(new PublishBatchCommand({
  TopicArn: "arn:aws:sns:us-east-1:123456789012:OrderProcessing.fifo",
  PublishRequestEntries: [
    {
      Id: "order1",
      Message: "Order 1 processing",
      MessageGroupId: "order-group-1",
      MessageDeduplicationId: "order-1-dedup"
    },
    {
      Id: "order2",
      Message: "Order 2 processing", 
      MessageGroupId: "order-group-1",
      MessageDeduplicationId: "order-2-dedup"
    },
    {
      Id: "order3",
      Message: "Order 3 processing",
      MessageGroupId: "order-group-2", 
      MessageDeduplicationId: "order-3-dedup"
    }
  ]
}));

Message Formatting

JSON Message Structure

For platform-specific message formatting, use JSON message structure to send different payloads to different protocols.

interface JSONMessageStructure {
  default: string; // Default message for unsupported protocols
  email?: string;  // Email-specific message
  http?: string;   // HTTP endpoint message
  https?: string;  // HTTPS endpoint message  
  sqs?: string;    // SQS queue message
  sms?: string;    // SMS message
  APNS?: string;   // Apple Push Notification Service
  APNS_SANDBOX?: string; // APNS sandbox
  GCM?: string;    // Google Cloud Messaging
  ADM?: string;    // Amazon Device Messaging
  BAIDU?: string;  // Baidu Cloud Push
  MPNS?: string;   // Microsoft Push Notification Service  
  WNS?: string;    // Windows Push Notification Service
  MACOS?: string;  // macOS notifications
  MACOS_SANDBOX?: string; // macOS sandbox
}

JSON Message Example:

const jsonMessage = {
  default: "New notification available",
  email: "You have a new notification. Please check your dashboard.",
  sms: "New notification - check app",
  APNS: JSON.stringify({
    aps: {
      alert: {
        title: "New Notification",
        body: "You have a new message"
      },
      badge: 1,
      sound: "default",
      "content-available": 1
    },
    customData: {
      notificationId: "12345",
      category: "message"
    }
  }),
  GCM: JSON.stringify({
    notification: {
      title: "New Notification",
      body: "You have a new message"
    },
    data: {
      notificationId: "12345",
      category: "message"
    }
  })
};

await client.send(new PublishCommand({
  TopicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
  Message: JSON.stringify(jsonMessage),
  MessageStructure: "json"
}));

Message Attribute Data Types

Comprehensive list of supported data types for message attributes.

interface MessageAttributeDataTypes {
  /** String data type */
  String: string;
  /** Numeric data type */
  Number: string;
  /** Binary data type */
  Binary: string;
  /** Custom string types with namespace */
  'String.customType': string;
  /** Custom number types */
  'Number.customType': string;
  /** Custom binary types */
  'Binary.customType': string;
}

Common Custom Data Types:

  • String.Array - Array of strings (use StringListValues)
  • Binary.Array - Array of binary data (use BinaryListValues)
  • Number.currency - Monetary values
  • Number.timestamp - Unix timestamps
  • String.email - Email addresses
  • String.url - URLs

Publishing Patterns

High-Throughput Publishing:

// Use batch publishing for better performance
const publishBatch = async (messages: string[]) => {
  const batches: string[][] = [];
  for (let i = 0; i < messages.length; i += 10) {
    batches.push(messages.slice(i, i + 10));
  }
  
  for (const batch of batches) {
    const entries = batch.map((message, index) => ({
      Id: `msg-${index}`,
      Message: message
    }));
    
    await client.send(new PublishBatchCommand({
      TopicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
      PublishRequestEntries: entries
    }));
  }
};

Error Handling:

import { 
  InvalidParameterException, 
  ThrottledException,
  InternalErrorException 
} from "@aws-sdk/client-sns";

try {
  const result = await client.send(new PublishCommand({
    TopicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
    Message: "Test message"
  }));
  
  console.log("Message published:", result.MessageId);
} catch (error) {
  if (error instanceof InvalidParameterException) {
    console.log("Invalid parameter:", error.message);
  } else if (error instanceof ThrottledException) {
    console.log("Request throttled, retry later");
  } else if (error instanceof InternalErrorException) {
    console.log("Service error, retry");
  } else {
    console.log("Unknown error:", error);
  }
}

Retry Logic for Batch Publishing:

const publishBatchWithRetry = async (
  entries: PublishBatchRequestEntry[], 
  maxRetries = 3
) => {
  let retryCount = 0;
  let remainingEntries = entries;
  
  while (remainingEntries.length > 0 && retryCount < maxRetries) {
    try {
      const result = await client.send(new PublishBatchCommand({
        TopicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
        PublishRequestEntries: remainingEntries
      }));
      
      // Process successful entries
      result.Successful?.forEach(success => {
        console.log(`Published message ${success.Id}: ${success.MessageId}`);
      });
      
      // Retry failed entries  
      remainingEntries = result.Failed?.map(failure => 
        remainingEntries.find(entry => entry.Id === failure.Id)
      ).filter(Boolean) || [];
      
      if (remainingEntries.length > 0) {
        retryCount++;
        await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
      }
    } catch (error) {
      retryCount++;
      if (retryCount >= maxRetries) throw error;
      await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
    }
  }
};