or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdmessage-filtering.mdpolicy-management.mdsubscription-management.mdtopic-management.md
tile.json

message-filtering.mddocs/

Message Filtering

⚠️ DEPRECATION NOTICE: AWS CDK v1 has reached End-of-Support on 2023-06-01. Consider migrating to AWS CDK v2.

Advanced filter policy system for selective message delivery based on message attributes, supporting string conditions, numeric conditions, and existence checks.

Capabilities

SubscriptionFilter Class

Creates filters for selective message delivery based on message attributes.

/**
 * A subscription filter for an attribute
 */
class SubscriptionFilter {
  /**
   * Create a subscription filter with custom conditions
   * @param conditions - Array of filter conditions
   */
  constructor(conditions: any[]);
  
  /** The filter conditions array */
  readonly conditions: any[];
}

String Filtering

Create filters for string-based message attributes.

/**
 * Returns a subscription filter for a string attribute
 * @param stringConditions - String matching conditions
 */
static stringFilter(stringConditions: StringConditions): SubscriptionFilter;

Usage Examples:

import { SubscriptionFilter } from '@aws-cdk/aws-sns';

// Allow specific values
const eventTypeFilter = SubscriptionFilter.stringFilter({
  allowlist: ['order-created', 'order-updated', 'order-cancelled']
});

// Deny specific values
const notTestFilter = SubscriptionFilter.stringFilter({
  denylist: ['test-event', 'debug-event']
});

// Prefix matching
const orderEventFilter = SubscriptionFilter.stringFilter({
  matchPrefixes: ['order-', 'payment-']
});

// Combined conditions
const complexFilter = SubscriptionFilter.stringFilter({
  allowlist: ['production', 'staging'],
  matchPrefixes: ['user-'],
  denylist: ['user-test']
});

Numeric Filtering

Create filters for numeric message attributes.

/**
 * Returns a subscription filter for a numeric attribute
 * @param numericConditions - Numeric comparison conditions
 */
static numericFilter(numericConditions: NumericConditions): SubscriptionFilter;

Usage Examples:

// Exact value matching
const priorityFilter = SubscriptionFilter.numericFilter({
  allowlist: [1, 2, 3]
});

// Range filtering
const priceRangeFilter = SubscriptionFilter.numericFilter({
  between: { start: 100, stop: 1000 }
});

// Comparison filtering
const highValueFilter = SubscriptionFilter.numericFilter({
  greaterThan: 500
});

// Complex numeric filtering
const complexNumericFilter = SubscriptionFilter.numericFilter({
  greaterThanOrEqualTo: 18,
  lessThan: 65,
  allowlist: [21, 25, 30] // Special values
});

Existence Filtering

Create filters that check for the presence of attributes.

/**
 * Returns a subscription filter for attribute key matching
 */
static existsFilter(): SubscriptionFilter;

Usage Examples:

// Check if attribute exists
const hasUserIdFilter = SubscriptionFilter.existsFilter();

// Use in filter policy
const filterPolicy = {
  userId: SubscriptionFilter.existsFilter(), // Must have userId attribute
  eventType: SubscriptionFilter.stringFilter({
    allowlist: ['user-login', 'user-logout']
  })
};

Filter Condition Interfaces

StringConditions Interface

String attribute filter conditions.

/**
 * Conditions that can be applied to string attributes
 */
interface StringConditions {
  /** @deprecated use allowlist */
  whitelist?: string[];
  
  /** @deprecated use denylist */
  blacklist?: string[];
  
  /** Match one or more values */
  allowlist?: string[];
  
  /** Match any value that doesn't include any of the specified values */
  denylist?: string[];
  
  /** Matches values that begin with the specified prefixes */
  matchPrefixes?: string[];
}

NumericConditions Interface

Numeric attribute filter conditions.

/**
 * Conditions that can be applied to numeric attributes
 */
interface NumericConditions {
  /** @deprecated use allowlist */
  whitelist?: number[];
  
  /** Match one or more values */
  allowlist?: number[];
  
  /** Match values that are greater than the specified value */
  greaterThan?: number;
  
  /** Match values that are greater than or equal to the specified value */
  greaterThanOrEqualTo?: number;
  
  /** Match values that are less than the specified value */
  lessThan?: number;
  
  /** Match values that are less than or equal to the specified value */
  lessThanOrEqualTo?: number;
  
  /** Match values that are between the specified values (inclusive) */
  between?: BetweenCondition;
  
  /** Match values that are strictly between the specified values (exclusive) */
  betweenStrict?: BetweenCondition;
}

BetweenCondition Interface

Range condition for numeric filters.

/**
 * Between condition for a numeric attribute
 */
interface BetweenCondition {
  /** The start value */
  start: number;
  
  /** The stop value */
  stop: number;
}

Complex Filter Policy Examples

E-commerce Order Processing

import { SubscriptionFilter } from '@aws-cdk/aws-sns';

const orderProcessingFilter = {
  // Only process orders for specific store regions
  storeRegion: SubscriptionFilter.stringFilter({
    allowlist: ['us-east', 'us-west', 'eu-central']
  }),
  
  // Only high-value orders
  orderValue: SubscriptionFilter.numericFilter({
    greaterThanOrEqualTo: 100
  }),
  
  // Exclude test orders
  environment: SubscriptionFilter.stringFilter({
    denylist: ['test', 'development']
  }),
  
  // Must have customer ID
  customerId: SubscriptionFilter.existsFilter()
};

new Subscription(this, 'OrderProcessor', {
  topic: orderTopic,
  protocol: SubscriptionProtocol.SQS,
  endpoint: processingQueue.queueArn,
  filterPolicy: orderProcessingFilter
});

User Event Analytics

const analyticsFilter = {
  // Track specific user actions
  eventType: SubscriptionFilter.stringFilter({
    matchPrefixes: ['user-', 'session-'],
    denylist: ['user-test']
  }),
  
  // Only for active users
  userTier: SubscriptionFilter.stringFilter({
    allowlist: ['premium', 'standard']
  }),
  
  // Session duration tracking
  sessionDuration: SubscriptionFilter.numericFilter({
    between: { start: 60, stop: 3600 } // 1 minute to 1 hour
  })
};

IoT Device Monitoring

const deviceMonitoringFilter = {
  // Critical alerts only
  alertLevel: SubscriptionFilter.stringFilter({
    allowlist: ['critical', 'high']
  }),
  
  // Temperature sensors
  sensorType: SubscriptionFilter.stringFilter({
    matchPrefixes: ['temp-', 'humidity-']
  }),
  
  // Abnormal readings
  value: SubscriptionFilter.numericFilter({
    lessThan: -10, // Too cold
    greaterThan: 50 // Too hot
  }),
  
  // Must have device location
  location: SubscriptionFilter.existsFilter()
};

Filter Policy Limitations

SNS filter policies have several important limitations:

  1. Maximum Attributes: A filter policy can have a maximum of 5 attribute names
  2. Total Combinations: The total combination of values must not exceed 100
  3. Message Size: Filter policies count toward the message size limit
  4. Evaluation Logic: Conditions within an attribute are OR'ed, conditions across attributes are AND'ed
// This filter policy violates the combination limit (3 * 4 * 10 = 120 > 100)
const invalidFilter = {
  region: SubscriptionFilter.stringFilter({
    allowlist: ['us-east', 'us-west', 'eu-central'] // 3 values
  }),
  environment: SubscriptionFilter.stringFilter({
    allowlist: ['prod', 'staging', 'dev', 'test'] // 4 values  
  }),
  eventType: SubscriptionFilter.stringFilter({
    allowlist: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] // 10 values
  })
  // Total combinations: 3 * 4 * 10 = 120 (exceeds limit of 100)
};

Best Practices

  1. Keep It Simple: Use as few attributes as possible in filter policies
  2. Minimize Combinations: Be aware of the total combination limit
  3. Use Prefixes: Prefix matching is more flexible than exact matches
  4. Test Thoroughly: Verify filter policies work as expected with sample messages
  5. Document Filters: Complex filter policies should be well-documented
  6. Consider Alternatives: For complex routing, consider using multiple topics or Lambda-based routing
// Good: Simple, clear filter policy
const goodFilter = {
  eventType: SubscriptionFilter.stringFilter({
    matchPrefixes: ['order-']
  }),
  priority: SubscriptionFilter.stringFilter({
    allowlist: ['high', 'critical']
  })
};

// Better: Even simpler with meaningful semantics
const betterFilter = {
  route: SubscriptionFilter.stringFilter({
    allowlist: ['high-priority-orders']
  })
};