High-performance batch operations for sending, deleting, and changing visibility of multiple messages in single API calls, reducing request overhead and improving throughput.
Sends multiple messages in a single request (up to 10 messages per batch).
class SendMessageBatchCommand {
constructor(input: SendMessageBatchCommandInput);
}
interface SendMessageBatchCommandInput {
/** URL of the target queue */
QueueUrl: string;
/** Array of messages to send (up to 10) */
Entries: SendMessageBatchRequestEntry[];
}
interface SendMessageBatchRequestEntry {
/** Unique identifier for this entry (within the batch) */
Id: string;
/** Message payload (up to 1 MB) */
MessageBody: string;
/** Delay before message becomes available (0-900 seconds) */
DelaySeconds?: number;
/** Custom message attributes */
MessageAttributes?: Record<string, MessageAttributeValue>;
/** Deduplication ID for FIFO queues */
MessageDeduplicationId?: string;
/** Group ID for FIFO queues */
MessageGroupId?: string;
/** System-defined message attributes */
MessageSystemAttributes?: Record<MessageSystemAttributeNameForSends, MessageSystemAttributeValue>;
}
interface SendMessageBatchCommandOutput {
/** Successfully sent messages */
Successful: SendMessageBatchResultEntry[];
/** Failed message entries */
Failed: BatchResultErrorEntry[];
}
interface SendMessageBatchResultEntry {
/** Entry ID from the request */
Id: string;
/** Unique message identifier */
MessageId: string;
/** MD5 hash of the message body */
MD5OfBody: string;
/** MD5 hash of message attributes */
MD5OfMessageAttributes?: string;
/** MD5 hash of system attributes */
MD5OfMessageSystemAttributes?: string;
/** FIFO sequence number */
SequenceNumber?: string;
}Usage Examples:
import { SQSClient, SendMessageBatchCommand } from "@aws-sdk/client-sqs";
const client = new SQSClient({ region: "us-east-1" });
// Send multiple messages in batch
const batchResult = await client.send(new SendMessageBatchCommand({
QueueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue",
Entries: [
{
Id: "msg1",
MessageBody: JSON.stringify({ orderId: "12345", status: "pending" })
},
{
Id: "msg2",
MessageBody: JSON.stringify({ orderId: "12346", status: "processing" }),
MessageAttributes: {
Priority: {
StringValue: "high",
DataType: "String"
}
}
},
{
Id: "msg3",
MessageBody: JSON.stringify({ orderId: "12347", status: "completed" }),
DelaySeconds: 60
}
]
}));
// Process results
console.log(`Successfully sent ${batchResult.Successful.length} messages`);
for (const success of batchResult.Successful) {
console.log(`Message ${success.Id} sent with ID: ${success.MessageId}`);
}
if (batchResult.Failed.length > 0) {
console.log(`Failed to send ${batchResult.Failed.length} messages`);
for (const failure of batchResult.Failed) {
console.log(`Message ${failure.Id} failed: ${failure.Message}`);
}
}
// Send FIFO batch
const fifoBatch = await client.send(new SendMessageBatchCommand({
QueueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/MyFifoQueue.fifo",
Entries: [
{
Id: "order1",
MessageBody: "Order 1 data",
MessageGroupId: "group1",
MessageDeduplicationId: "dedup1"
},
{
Id: "order2",
MessageBody: "Order 2 data",
MessageGroupId: "group1",
MessageDeduplicationId: "dedup2"
}
]
}));Deletes multiple messages in a single request using their receipt handles.
class DeleteMessageBatchCommand {
constructor(input: DeleteMessageBatchCommandInput);
}
interface DeleteMessageBatchCommandInput {
/** URL of the queue containing the messages */
QueueUrl: string;
/** Array of messages to delete (up to 10) */
Entries: DeleteMessageBatchRequestEntry[];
}
interface DeleteMessageBatchRequestEntry {
/** Unique identifier for this entry (within the batch) */
Id: string;
/** Receipt handle of the message to delete */
ReceiptHandle: string;
}
interface DeleteMessageBatchCommandOutput {
/** Successfully deleted messages */
Successful: DeleteMessageBatchResultEntry[];
/** Failed delete entries */
Failed: BatchResultErrorEntry[];
}
interface DeleteMessageBatchResultEntry {
/** Entry ID from the request */
Id: string;
}Usage Examples:
// Receive messages for batch processing
const received = await client.send(new ReceiveMessageCommand({
QueueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue",
MaxNumberOfMessages: 10
}));
const deleteEntries: DeleteMessageBatchRequestEntry[] = [];
const messages = received.Messages || [];
// Process each message
for (let i = 0; i < messages.length; i++) {
const message = messages[i];
try {
// Process message
await processMessage(message.Body);
// Add to delete batch
deleteEntries.push({
Id: `delete_${i}`,
ReceiptHandle: message.ReceiptHandle!
});
} catch (error) {
console.error(`Failed to process message ${message.MessageId}:`, error);
}
}
// Delete successfully processed messages in batch
if (deleteEntries.length > 0) {
const deleteResult = await client.send(new DeleteMessageBatchCommand({
QueueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue",
Entries: deleteEntries
}));
console.log(`Successfully deleted ${deleteResult.Successful.length} messages`);
// Handle failed deletes
for (const failure of deleteResult.Failed) {
console.log(`Failed to delete message ${failure.Id}: ${failure.Message}`);
}
}
async function processMessage(body: string | undefined) {
if (!body) return;
const data = JSON.parse(body);
// Process the message
console.log("Processing:", data);
}Changes visibility timeout for multiple messages in a single request.
class ChangeMessageVisibilityBatchCommand {
constructor(input: ChangeMessageVisibilityBatchCommandInput);
}
interface ChangeMessageVisibilityBatchCommandInput {
/** URL of the queue containing the messages */
QueueUrl: string;
/** Array of visibility changes (up to 10) */
Entries: ChangeMessageVisibilityBatchRequestEntry[];
}
interface ChangeMessageVisibilityBatchRequestEntry {
/** Unique identifier for this entry (within the batch) */
Id: string;
/** Receipt handle of the message */
ReceiptHandle: string;
/** New visibility timeout in seconds (0-43200) */
VisibilityTimeoutSeconds?: number;
}
interface ChangeMessageVisibilityBatchCommandOutput {
/** Successfully updated messages */
Successful: ChangeMessageVisibilityBatchResultEntry[];
/** Failed update entries */
Failed: BatchResultErrorEntry[];
}
interface ChangeMessageVisibilityBatchResultEntry {
/** Entry ID from the request */
Id: string;
}Usage Examples:
// Receive messages for long processing
const received = await client.send(new ReceiveMessageCommand({
QueueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue",
MaxNumberOfMessages: 10
}));
// Extend visibility for all messages that need longer processing
const visibilityEntries: ChangeMessageVisibilityBatchRequestEntry[] = [];
for (let i = 0; i < (received.Messages?.length || 0); i++) {
const message = received.Messages![i];
// Check if message needs extended processing time
if (requiresLongProcessing(message.Body)) {
visibilityEntries.push({
Id: `extend_${i}`,
ReceiptHandle: message.ReceiptHandle!,
VisibilityTimeoutSeconds: 600 // 10 minutes
});
}
}
// Apply visibility changes in batch
if (visibilityEntries.length > 0) {
const visibilityResult = await client.send(new ChangeMessageVisibilityBatchCommand({
QueueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue",
Entries: visibilityEntries
}));
console.log(`Extended visibility for ${visibilityResult.Successful.length} messages`);
}
function requiresLongProcessing(body: string | undefined): boolean {
if (!body) return false;
try {
const data = JSON.parse(body);
return data.processingType === 'long-running';
} catch {
return false;
}
}interface BatchResultErrorEntry {
/** Entry ID from the request */
Id: string;
/** Whether the error is sender's fault */
SenderFault: boolean;
/** Error code */
Code: string;
/** Error message */
Message?: string;
}Common batch operation errors:
Usage Examples:
// Robust batch processing with error handling
async function sendMessagesBatch(queueUrl: string, messages: Array<{id: string, body: string}>) {
// Split into chunks of 10 (SQS batch limit)
const chunks = [];
for (let i = 0; i < messages.length; i += 10) {
chunks.push(messages.slice(i, i + 10));
}
const results = {
successful: [] as string[],
failed: [] as Array<{id: string, error: string}>
};
for (const chunk of chunks) {
try {
const batchResult = await client.send(new SendMessageBatchCommand({
QueueUrl: queueUrl,
Entries: chunk.map(msg => ({
Id: msg.id,
MessageBody: msg.body
}))
}));
// Collect successful sends
results.successful.push(...batchResult.Successful.map(s => s.Id));
// Collect failed sends for retry
for (const failure of batchResult.Failed) {
results.failed.push({
id: failure.Id,
error: failure.Message || 'Unknown error'
});
}
} catch (error) {
// Handle batch-level errors
console.error("Batch send failed:", error);
results.failed.push(...chunk.map(msg => ({
id: msg.id,
error: error.message || 'Batch operation failed'
})));
}
}
return results;
}
// Usage
const messages = [
{ id: "msg1", body: "Message 1" },
{ id: "msg2", body: "Message 2" },
// ... up to any number of messages (will be batched automatically)
];
const result = await sendMessagesBatch(queueUrl, messages);
console.log(`Sent ${result.successful.length} messages, ${result.failed.length} failed`);// Optimal batch sizes for different operations
const BATCH_SIZE = 10; // Maximum allowed by SQS
// For high-throughput scenarios, always use full batches
const messagesToSend = largeMessageArray;
const batches = [];
for (let i = 0; i < messagesToSend.length; i += BATCH_SIZE) {
batches.push(messagesToSend.slice(i, i + BATCH_SIZE));
}
for (const batch of batches) {
await client.send(new SendMessageBatchCommand({
QueueUrl: queueUrl,
Entries: batch.map((msg, index) => ({
Id: `batch_${Date.now()}_${index}`,
MessageBody: msg
}))
}));
}// Implement exponential backoff for failed batch entries
async function sendWithRetry(entries: SendMessageBatchRequestEntry[], queueUrl: string, maxRetries = 3) {
let remainingEntries = [...entries];
let attempt = 0;
while (remainingEntries.length > 0 && attempt < maxRetries) {
const result = await client.send(new SendMessageBatchCommand({
QueueUrl: queueUrl,
Entries: remainingEntries
}));
// Remove successful entries
const failedIds = new Set(result.Failed.map(f => f.Id));
remainingEntries = remainingEntries.filter(entry => failedIds.has(entry.Id));
if (remainingEntries.length > 0) {
attempt++;
// Exponential backoff
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
return remainingEntries; // Any remaining failed entries
}