Menu
Amazon Simple Notification Service
Developer Guide (API Version 2010-03-31)

Filtering Messages with Amazon SNS

By default, a subscriber of an Amazon SNS topic receives every message published to the topic. To receive only a subset of the messages, a subscriber assigns a filter policy to the topic subscription.

A filter policy is a simple JSON object. The policy contains attributes that define which messages the subscriber receives. When you publish a message to a topic, Amazon SNS compares the message attributes to the attributes in the filter policy for each of the topic's subscriptions. If there is a match between the attributes, Amazon SNS sends the message to the subscriber. Otherwise, Amazon SNS skips the subscriber without sending the message to it.

With filter policies, you can simplify your usage of Amazon SNS by consolidating your message filtering criteria into your topic subscriptions. With this consolidation, you can offload the message filtering logic from subscribers and the message routing logic from publishers. Therefore, you don't need to filter messages by creating a separate topic for each filtering condition. Instead, you can use a single topic, and you can differentiate your messages with attributes. Each subscriber receives and processes only those messages accepted by its filter policy.

For example, you could use a single topic to publish all messages generated by transactions from your online retail site. To each message, you could assign an attribute that indicates the type of transaction, such as order_placed, order_cancelled, or order_declined. By creating subscriptions with filter policies, you can route each message to the queue that is meant to process the message's transaction type.

For a tutorial demonstrating how to implement message filtering with the AWS Management Console, see Filter Messages Published to Topics. This tutorial shows how to apply filter policies to route messages to separate Amazon SQS queues.

Subscription Filter Policies

You assign filter policies to Amazon SNS subscriptions. In a policy, you specify attribute names, and for each name, you assign a list of one or more values. A subscription accepts a message only if the message contains attributes that match those specified in the subscription's filter policy. Specifically, the subscription accepts the message if:

  1. Each attribute name in the filter policy matches an attribute name assigned to the message.

  2. For each matching attribute name, at least one match exists between the values that are assigned to that name in the filter policy and the message.

When Amazon SNS evaluates the message attributes against the policy, it ignores message attributes that are not specified in the policy.

When you create a filter policy, remember the following constraints:

  • Amazon SNS compares the policy attributes only to message attributes that have a data type of String or String.Array. Message attributes with data types Number or Binary are ignored.

  • The attribute comparison between policy and message is case-sensitive.

  • As a JSON object, the filter policy can contain strings enclosed in quotes, numbers, and the unquoted keywords true, false, and null.

  • Numbers are compared as strings, so the numbers 300, 300.0, and 3.0e2 are not equal.

  • A filter policy can have up to 10 attribute names.

  • The maximum size of a policy is 256 KB.

  • The policy must be a valid UTF-8 string.

  • By default, you can have up to 100 filter policies per AWS account per region. To increase this limit, submit an SNS Limit Increase case.

  • The total combination of values must not exceed 100. Calculate the total combination by multiplying the number of values in each array. For example, in the following policy, the first array has 3 values, the second has 1 value, and the third has 2 values. The total combination is calculated as 3 x 1 x 2 = 6.

    {
      "key_a": ["value_one", "value_two", "value_three"],
      "key_b": ["value_one"],
      "key_c": ["value_one", "value_two"]
    }

The following examples show how filter policies might accept or reject a message published to a topic.

Example Message with Attributes

The following example shows a message payload sent by an Amazon SNS topic that publishes customer transactions. The message includes attributes that describe the transaction: the name of the store, the type of event, and the interests specified by the customer who placed the order.

{
  "Type" : "Notification",
  "MessageId" : "e3c4e17a-819b-5d95-a0e8-b306c25afda0",
  "TopicArn" : "arn:aws:sns:us-east-1:111122223333:MySnsTopic",
  "Message" : message body with transaction details . . .
  "Timestamp" : "2017-11-07T23:28:01.631Z",
  "SignatureVersion" : "1",
  "Signature" : signature . . .
  "UnsubscribeURL" : unsubscribe URL . . .
  "MessageAttributes" : {
    "customer_interests" : {"Type":"String.Array","Value":"[\"soccer\", \"rugby\", \"hockey\"]"},
    "store" : {"Type":"String","Value":"example_corp"},
    "event" : {"Type":"String","Value":"order_placed"}
  }
}

For information about applying attributes to a message, see Using Amazon SNS Message Attributes.

Because this message includes attributes, any topic subscription that includes a filter policy can selectively receive or reject the message.

Filter Policies That Accept the Example Message

The following policy accepts the example message because the attribute names and values in the policy match those assigned to the message:

{
    "store": ["example_corp"],
    "event": ["order_placed"]
}

The following policy includes multiple attribute values. The policy accepts the example message because at least one value, rugby, matches a value assigned to customer_interests in the message attributes:

{
    "customer_interests": ["rugby", "football", "baseball"]
}

Filter Policies That Reject the Example Message

The following polices reject the example message because of mismatches between the policy and message attributes.

In the following policy, the attribute value, order_cancelled, does not match the value assigned to event in the message attributes:

{
  "store": ["example_corp"],
  "event": ["order_cancelled"]
}

The following policy includes an attribute name, encrypted, which is not present in the message attributes:

{
  "store": ["example_corp"],
  "event": ["order_placed"],
  "encrypted": [false]
}

In the following policy, neither the basketball or baseball values match a value assigned to customer_interests in the message attributes:

{
    "customer_interests": ["basketball", "baseball"]
}

Applying Subscription Filter Policies

You can apply a filter policy to an Amazon SNS subscription by using the Amazon SNS console. Or, to apply policies programmatically, you can use the Amazon SNS API, the AWS Command Line Interface (AWS CLI), or any AWS SDK that supports Amazon SNS, such as the AWS SDK for Java.

Applying a Filter Policy with the Console

Complete the following steps to apply a filter policy using the Amazon SNS console:

  1. Sign in to the AWS Management Console and open the Amazon SNS console at https://console.aws.amazon.com/sns/v2/home.

  2. In the navigation pane, choose Subscriptions. The Subscriptions page provides all of the Amazon SNS subscriptions that you have in the selected region.

  3. If you don't have a subscription, choose Create subscription, and provide values for Topic ARN, Protocol, and Endpoint.

  4. If you have one or more subscriptions, select the subscription to which you want to apply a filter policy.

  5. Choose Actions, and choose Edit subscription filter policy in the menu.

  6. In the Edit subscription filter policy window, provide the JSON body of your filter policy.

  7. Choose Set subscription filter policy. Amazon SNS applies your filter policy to the subscription.

Applying a Filter Policy with the AWS CLI

To apply a filter policy with the AWS Command Line Interface (AWS CLI), use the set-subscription-attributes command, as shown in the following example:

Copy
$ aws sns set-subscription-attributes --subscription-arn arn:aws:sns: ... --attribute-name FilterPolicy --attribute-value '{"store":["example_corp"],"event":["order_placed"]}'

For the --attribute-name option, specify FilterPolicy. For --attribute-value, specify your JSON policy.

To provide valid JSON for your policy, enclose the attribute names and values in double quotes. You must also enclose the entire policy argument in quotes. To avoid escaping quotes, you can use single quotes to enclose the policy and double quotes to enclose the JSON names and values, as shown in the example.

To verify that your filter policy was applied, use the get-subscription-attributes command. The attributes in the terminal output should show your filter policy for the FilterPolicy key, as shown in the following example:

$ aws sns get-subscription-attributes --subscription-arn arn:aws:sns: ...
{
    "Attributes": {
        "Endpoint": "endpoint . . .", 
        "Protocol": "https",
        "RawMessageDelivery": "false", 
        "EffectiveDeliveryPolicy": "delivery policy . . .",
        "ConfirmationWasAuthenticated": "true", 
        "FilterPolicy": "{\"store\": [\"example_corp\"], \"event\": [\"order_placed\"]}", 
        "Owner": "111122223333", 
        "SubscriptionArn": "arn:aws:sns: . . .", 
        "TopicArn": "arn:aws:sns: . . ."
    }
}

Applying a Filter Policy with the SDK for Java

To apply a filter policy with the AWS SDK for Java, use the setSubscriptionAttributes method of the AmazonSNS client. Provide a SetSubscriptionAttributesRequest object as the argument, as shown in the following example:

Copy
AmazonSNS snsClient = AmazonSNSClientBuilder.defaultClient(); String filterPolicyString = "{\"store\":[\"example_corp\"],\"event\":[\"order_placed\"]}"; SetSubscriptionAttributesRequest request = new SetSubscriptionAttributesRequest(subscriptionArn, "FilterPolicy", filterPolicyString); snsClient.setSubscriptionAttributes(request);

To initialize the SetSubscriptionAttributesRequest object, provide the following arguments:

  • subscriptionArn – The Amazon Resource Name (ARN) of the subscription to which the policy is applied.

  • attributeName – Must be "FilterPolicy".

  • attributeValue – Your JSON filter policy as a string. Because you must enclose the string policy in double quotes, remember to escape the double quotes that enclose the attribute names and values, as in \"store\".

The SetSubscriptionAttributesRequest class accepts the filter policy as a string. If you want to define your policy as a Java collection, create a map that associates each attribute name with a list of values. To assign the policy to a subscription, you first produce a string version of the policy from the contents of the map, and you then pass the string as the attributeValue argument to SetSubscriptionAttributesRequest.

To simplify this process, you can add the following example class to your application and modify it as needed:

Copy
import com.amazonaws.services.sns.AmazonSNS; import com.amazonaws.services.sns.model.SetSubscriptionAttributesRequest; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; public class SNSMessageFilterPolicy { private Map<String, ArrayList<String>> filterPolicy; public SNSMessageFilterPolicy() { filterPolicy = new HashMap<>(); } public void setFilterPolicy(Map<String, ArrayList<String>> filterPolicy) { this.filterPolicy = filterPolicy; } public Map<String, ArrayList<String>> getFilterPolicy() { return filterPolicy; } public <T> void addAttribute(String attributeName, T attributeValue) { ArrayList<T> attributeValueArray = new ArrayList<>(); attributeValueArray.add(attributeValue); addAttribute(attributeName, attributeValueArray); } public void addAttribute(String attributeName, ArrayList<?> attributeValues) { ArrayList<String> attributeValueStrings = new ArrayList<>(); for (Object o : attributeValues) { attributeValueStrings.add(o.toString()); } filterPolicy.put(attributeName, attributeValueStrings); } public void apply(AmazonSNS snsClient, String subscriptionArn) { SetSubscriptionAttributesRequest request = new SetSubscriptionAttributesRequest(subscriptionArn, "FilterPolicy", formatFilterPolicy()); snsClient.setSubscriptionAttributes(request); } public String formatFilterPolicy() { return filterPolicy.entrySet() .stream() .map(entry -> "\"" + entry.getKey() + "\": " + entry.getValue() .stream() .collect(Collectors.joining("\", \"", "[\"", "\"]"))) .collect(Collectors.joining(", ", "{", "}")); } }

This class stores a filterPolicy field as a map. You use the overloaded addAttribute methods to add attributes to your policy. These methods accept the attribute name as a string, and they accept the attribute value as a single generic item or a list of generic items. Because the values are generic, you can add values that are of string or primitive types (such as "rugby", 1, or false). When you are ready to apply your policy to a subscription, use the apply method, and provide an AmazonSNS client and subscription ARN. This method produces a policy string from the contents of the filterPolicy map, and it applies the policy to the specified subscription.

The following code shows how to initialize and use the example SNSMessageFilterPolicy class:

Copy
// Initialize example filter policy class SNSMessageFilterPolicy fp = new SNSMessageFilterPolicy(); // Add filter policy attribute with single value fp.addAttribute("store", "example_corp"); fp.addAttribute("event", "order_placed"); // Add filter policy attribute with a list of values ArrayList<String> attributeValues = new ArrayList<>(); attributeValues.add("rugby"); attributeValues.add("soccer"); attributeValues.add("hockey"); fp.addAttribute("customer_interests", attributeValues); // Add filter policy attribute with primitive value (boolean in this case) fp.addAttribute("encrypted", false); // Apply filter policy attributes to SNS subscription fp.apply(snsClient, subscriptionArn);

Applying a Filter Policy with the Amazon SNS API

To apply a filter policy with the Amazon SNS API, make a request to the SetSubscriptionAttributes action. Set the AttributeName parameter to FilterPolicy, and set the AttributeValue parameter to your filter policy JSON.