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. If a subscription lacks a filter policy, the subscription receives every message published to its topic.

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.

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, the customer interests, and the price of the purchase.

{ "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"}, "price_usd" : {"Type":"Number","Value":210.75} } }

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 accept or reject the message.

Example Filter Policies

The following filter policies accept or reject the example message based on their attribute names and values.

Example Policy That Accepts the Message

The attributes in the following policy match the attributes that are assigned to the example message:

{ "store": ["example_corp"], "event": [{"anything-but":"order_cancelled"}], "customer_interests": ["rugby", "football", "baseball"], "price_usd": [{"numeric":[">=", 100]}] }

If any single attribute in this policy doesn't match one that's assigned to the message, the policy rejects the message.

Example Policy That Rejects the Message

The following policy has multiple mismatches between its attributes and the attributes that are assigned to the example message:

{ "store": ["example_corp"], "event": ["order_cancelled"], "encrypted": [false], "customer_interests": ["basketball", "baseball"] }

One or more mismatches cause the policy to reject the message.

Because the encrypted attribute name isn't present in the message attributes, that policy attribute rejects the message, regardless of the value that's assigned to it.

Filter policy attributes can have string or numeric values. With string and numeric values, you can use the following operations to match message attributes and filter messages.

String Value Matching

String values are enclosed in double quotes in your policy JSON. With strings, you can use the following operations to match message attributes.

Exact matching (whitelisting)

This matching occurs when a policy attribute value matches one or more message attribute values. For example, the policy attribute:

"customer_interests": ["rugby"]

Matches the message attribute:

"customer_interests" : {"Type":"String","Value":"rugby"}
Anything-but matching (blacklisting)

When a policy attribute value includes the anything-but keyword, it matches any message attribute that doesn't include the policy attribute value. For example, the policy attribute:

"customer_interests": [{"anything-but":"rugby"}]

Matches message attributes such as:

"customer_interests" : {"Type":"String","Value":"baseball"}

And:

"customer_interests" : {"Type":"String","Value":"football"}

But not:

"customer_interests" : {"Type":"String","Value":"rugby"}
Prefix matching

When a policy attribute includes the prefix keyword, its value matches any message attribute value that begins with the specified characters. For example, the policy attribute:

"customer_interests": [{"prefix":"bas"}]

Matches message attributes such as:

"customer_interests" : {"Type":"String","Value":"baseball"}

And:

"customer_interests" : {"Type":"String","Value":"basketball"}

But not:

"customer_interests" : {"Type":"String","Value":"rugby"}

Numeric Value Matching

Numeric values aren't enclosed in quotes in your policy JSON. With numeric values, you can use the following operations to match message attribute values.

Exact matching

When a policy attribute value includes the numeric keyword and the = operator, it matches any message attribute that has the same name and an equal numeric value. For example, the policy attribute:

"price_usd": [{"numeric":["=",301.5]}]

Matches message attributes such as:

"price_usd" : {"Type":"Number","Value":301.5}

And:

"price_usd" : {"Type":"Number","Value":3.015e2}
Range matching

In addition to the = operator, a numeric policy attribute can include <, <=, >, and >=. For example, the policy attribute:

"price_usd": [{"numeric":["<", 0]}]

Matches message attributes with negative numeric values, and:

"price_usd": [{"numeric":[">", 0, "<=", 150]}]

Matches message attributes with positive numbers up to 150.

AND/OR Logic

Apply AND/OR logic to your filter policies as follows.

AND logic

Apply AND logic by using multiple attribute names (keys). For example, the policy:

{ "customer_interests": ["rugby"], "price_usd": [{"numeric":[">", 100]}] }

Matches messages with a customer_interests value of rugby and a price_usd value that's over 100.

OR logic

Apply OR logic by assigning multiple values to an attribute name. For example, the policy attribute:

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

Matches messages with a customer_interests value of rugby or football or baseball.

Constraints

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, String.Array, or Number. Message attributes with the Binary data type are ignored.

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

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

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

  • A numeric policy attribute can have a value from -109 to 109, with 5 digits of accuracy after the decimal point.

  • The maximum size of a policy is 256 KB.

  • When you're using the Amazon SNS API, the policy JSON must be passed as a valid UTF-8 string.

  • By default, you can have up to 200 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 three values, the second has one value, and the third has two 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"] }

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 Using the AWS Management 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 chosen 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 Using 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:

$ 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 Using an AWS SDK

The following examples show how to apply filter policies by using the Amazon SNS clients that are provided by the AWS SDKs.

AWS SDK for JavaAWS SDK for .NET
AWS 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:

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. You then pass the string as the attributeValue argument to SetSubscriptionAttributesRequest.

AWS SDK for .NET

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

AmazonSimpleNotificationServiceClient snsClient = new AmazonSimpleNotificationServiceClient(); 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 C# collection, create a dictionary 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 dictionary. You then pass the string as the attributeValue argument to SetSubscriptionAttributesRequest.

Applying a Filter Policy Using 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.

Applying a Filter Policy Using AWS CloudFormation

To apply a filter policy using AWS CloudFormation, use a JSON or YAML template to create a AWS CloudFormation stack. For more information, see the FilterPolicy property of the AWS::SNS::Subscription resource in the AWS CloudFormation User Guide and the example AWS CloudFormation template.

  1. Sign in to the AWS CloudFormation console.

  2. Choose Create Stack.

  3. On the Select Template page, choose Upload a template to Amazon S3, select the file, and choose Next.

  4. On the Specify Details page, do the following:

    1. For Stack Name, type MyFilterPolicyStack.

    2. For myHttpEndpoint, type the HTTP endpoint to be subscribed to your topic.

      Tip

      If you don't have an HTTP endpoint, create one.

  5. On the Options page, choose Next.

  6. On the Review page, choose Create.

Removing Subscription Filter Policies

To stop filtering the messages that are sent to a subscription, remove the subscription's filter policy by overwriting it with an empty JSON body. After you remove the policy, the subscription accepts every message that's published to it.

Removing a Filter Policy Using the Console

Complete the following steps to remove a filter policy by 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 chosen region.

  3. Select the subscription that you want to remove the filter policy from.

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

  5. In the Edit subscription filter policy window, provide an empty JSON body for your filter policy: {}.

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

Removing a Filter Policy Using the AWS CLI

To remove a filter policy with the AWS CLI, use the set-subscription-attributes command and provide an empty JSON body for the --attribute-value argument:

$ aws sns set-subscription-attributes --subscription-arn arn:aws:sns: ... --attribute-name FilterPolicy --attribute-value "{}"

Removing a Filter Policies Using an AWS SDK

The following examples show how to remove filter policies by using the Amazon SNS clients that are provided by the AWS SDKs.

AWS SDK for JavaAWS SDK for .NET
AWS SDK for Java

To remove a filter policy with the AWS SDK for Java, use the setSubscriptionAttributes method of the AmazonSNS client. Provide a string that contains an empty JSON body as your filter policy:

AmazonSNS snsClient = AmazonSNSClientBuilder.defaultClient(); SetSubscriptionAttributesRequest request = new SetSubscriptionAttributesRequest(subscriptionArn, "FilterPolicy", "{}"); snsClient.setSubscriptionAttributes(request);
AWS SDK for .NET

To remove a filter policy with the AWS SDK for .NET, use the SetSubscriptionAttributes method of the AmazonSNS client. Provide a string that contains an empty JSON body as your filter policy:

AmazonSimpleNotificationServiceClient snsClient = new AmazonSimpleNotificationServiceClient(); SetSubscriptionAttributesRequest request = new SetSubscriptionAttributesRequest(subscriptionArn, "FilterPolicy", "{}"); snsClient.SetSubscriptionAttributes(request);

Removing a Filter Policy Using the Amazon SNS API

To remove a filter policy with the Amazon SNS API, make a request to the SetSubscriptionAttributes action. Set the AttributeName parameter to FilterPolicy, and provide an empty JSON body for the AttributeValue parameter.

Removing a Filter Policy Using AWS CloudFormation

To remove a filter policy using AWS CloudFormation, use a JSON or YAML template to create a AWS CloudFormation stack. For more information, see the FilterPolicy property of the AWS::SNS::Subscription resource in the AWS CloudFormation User Guide and the example AWS CloudFormation template.

Note

Replace the existing FilterPolicy with an empty JSON body.

  1. Sign in to the AWS CloudFormation console.

  2. From the list of stacks, choose the stack that contains your filter policy, for example MyFilterPolicyStack.

  3. Choose Actions, Delete Stack.

  4. On the Delete Stack page, choose Yes, Delete.

    AWS CloudFormation begins to delete the MyFilterPolicyStack stack and displays the DELETE_IN_PROGRESS status. When the process is complete, the stack is removed from the list.

Example: Filter Policy as a Java Collection

When you provide a filter policy to the Amazon SNS client in one of the AWS SDKs, you provide the policy as a string. If you want to define your policy as a 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. Then, you pass the string to the Amazon SNS client.

The following example Java class demonstrates this process:

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 enum AttributeType { String, Numeric, Prefix, List, AnythingBut } private class Attribute<T> { protected final T value; protected final AttributeType type; public Attribute(AttributeType type, T value) { this.value = value; this.type = type; } public String toString() { switch(type) { case Prefix: return String.format("{\"prefix\":\"%s\"}", value.toString()); case Numeric: return String.format("{\"numeric\":%s}", value.toString()); case List: ArrayList<T> values = (ArrayList<T>)value; return values .stream() .map(entry -> entry.toString()) .collect(Collectors.joining(",")); case AnythingBut: return String.format("{\"anything-but\":\"%s\"}", value); default: return String.format("\"%s\"", value); } } } private class NumericValue<T extends Number> { private final T lower; private final T upper; private final String lowerOp; private final String upperOp; public NumericValue(String op, T value) { lower = value; lowerOp = op; upper = null; upperOp = null; } public NumericValue(String lowerOp, T lower, String upperOp, T upper) { this.lower = lower; this.lowerOp = lowerOp; this.upper = upper; this.upperOp = upperOp; } public String toString() { StringBuffer s = new StringBuffer("[") .append('\"').append(lowerOp).append("\",").append(lower); if (upper != null) { s.append(",\"").append(upperOp).append("\",").append(upper); } s.append("]"); return s.toString(); } } private final Map<String, Attribute> filterPolicy = new HashMap<>(); public void addAttribute(String attributeName, String attributeValue) { filterPolicy.put(attributeName, new Attribute(AttributeType.String, attributeValue)); } public void addAttribute(String attributeName, ArrayList<String> attributeValues) { ArrayList<Attribute> attributes = new ArrayList<>(); for (String s : attributeValues) { attributes.add(new Attribute(AttributeType.String, s)); } filterPolicy.put(attributeName, new Attribute(AttributeType.List, attributes)); } public void addAttributePrefix(String attributeName, String prefix) { filterPolicy.put(attributeName, new Attribute(AttributeType.Prefix, prefix)); } public void addAttributeAnythingBut(String attributeName, String value) { filterPolicy.put(attributeName, new Attribute(AttributeType.AnythingBut, value)); } public <T extends Number> void addAttribute(String attributeName, String op, T value) { filterPolicy.put(attributeName, new Attribute(AttributeType.Numeric, new NumericValue(op, value))); } public <T extends Number> void addAttributeRange( String attributeName, String lowerOp, T lower, String upperOp, T upper) { filterPolicy.put( attributeName, new Attribute(AttributeType.Numeric, new NumericValue(lowerOp, lower, upperOp, upper))); } 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() + "]") .collect(Collectors.joining(", ", "{", "}")); } }

This class stores a filterPolicy field as a map. You use the different addAttribute methods to add attributes to your policy. These methods accept the attribute name as a string, and they are specialized to accept different types of values. You can pass values as strings, lists of strings, numbers, or number ranges. You can add anything-but and prefix attributes. When you're 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:

// 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 a prefix attribute filterPolicy.addAttributePrefix("customer_interests", "bas"); // Add an anything-but attribute filterPolicy.addAttributeAnythingBut("customer_interests", "baseball"); // 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 numeric attribute filterPolicy.addAttribute("price_usd", "=", 0); // Add numeric attribute with a range filterPolicy.addAttributeRange("price_usd", ">", 0, "<=", 100); // Apply filter policy attributes to SNS subscription fp.apply(snsClient, subscriptionArn);