SQS message attributes are how you attach arbitrary metadata to your messages, and they’re surprisingly powerful for routing and filtering without needing to deserialize the message body.

Let’s see this in action. Imagine we have a system processing customer orders. We want to route high-priority orders to a dedicated queue. We can use message attributes for this.

Here’s a sample message sent to SQS using the AWS CLI:

aws sqs send-message \
    --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/my-order-queue \
    --message-body "Order Details: Item A, 2 units" \
    --message-attributes '{"Priority":{"StringValue":"High","DataType":"String"}}'

When a consumer receives this message, it can inspect the Priority attribute:

aws sqs receive-message \
    --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/my-order-queue \
    --attribute-names All

The output will include the Attributes section:

{
    "Messages": [
        {
            "MessageId": "...",
            "ReceiptHandle": "...",
            "MD5OfBody": "...",
            "Body": "Order Details: Item A, 2 units",
            "Attributes": {
                "Priority": {
                    "StringValue": "High",
                    "DataType": "String"
                }
            },
            "MD5OfMessageAttributes": "..."
        }
    ]
}

This allows the consumer to decide whether to process the message immediately, send it to a different queue, or take other actions based on the metadata, all without parsing the Body.

The core problem message attributes solve is decoupling message content from its processing instructions or context. Without them, you’d either need to embed routing information within the message body (requiring all consumers to parse and understand it) or rely on separate systems to manage this routing. Message attributes provide a first-class, SQS-native way to attach this metadata.

Internally, SQS stores these attributes alongside the message body. When you send a message, you specify the attribute name, its value, and its data type. SQS then indexes these attributes, making them available for filtering at receive time. The supported data types are String, Binary, Number (for strings representing numbers), and String.Array.

The primary lever you control is the schema and naming of your attributes. Consistency here is key. Deciding on a set of standard attributes (like Priority, Region, EventType) and their expected values will make your system predictable. You can also use attributes to store non-sensitive identifiers or references that your consumers will need. For example, an AccountId attribute could let a consumer quickly look up customer-specific configurations.

The number of message attributes per message is limited to 10, and the total size of message attributes is limited to 256 KB. This constraint forces you to be judicious about what metadata you attach, focusing on essential routing and filtering information rather than large payloads.

When you use ReceiveMessage with AttributeNames set to All, SQS returns all message attributes. However, for efficiency and cost savings, you can specify only the attributes you need using MessageAttributeNames. For instance, aws sqs receive-message --queue-url ... --message-attribute-names "Priority" "Region" will only return those specific attributes if they exist.

The next step is to explore how these attributes can be leveraged for sophisticated filtering using SQS’s MessageAttribute filtering capabilities directly within ReceiveMessage calls, enabling you to poll only for messages matching specific criteria.

Want structured learning?

Take the full Sqs course →