SNS

Stream can send payloads of all events from your application to an Amazon SNS topic you own.

A chat application with a lot of users generates a lots of events. With a standard Webhook configuration, events are posted to your server and can overwhelm unprepared servers during high-use periods. While the server is out, it will not be able to receive Webhooks and will fail to process them. One way to avoid this issue is to use Stream Chat's support for sending webhooks to Amazon SNS.

SNS removes the chance of losing data for Chat events by providing a large, scalable message exchange that delivers events generated by Stream Chat to as many consumers as you like.

The complete list of supported events is identical to those sent through webhooks and can be found on the Events page.

Configuration

You can configure your SNS topic through the Stream Dashboard or programmatically using the REST API or an SDK with Server Side Authorization.

There are 2 ways to configure authentication on your SNS topic:

  1. By providing a key and secret

  2. Or by having Stream's AWS account assume a role on your SNS topic. With this option you omit the key and secret, but instead you set up a resource-based policy to grant Stream Publish permission on your SNS topic. The following policy needs to be attached to your topic (replace the value of Resource with the fully qualified ARN of your topic):

{
  "Sid": "AllowStreamProdAccount",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::185583345998:root"
  },
  "Action": "SNS:Publish",
  "Resource": "arn:aws:sns:us-west-2:1111111111:customer-sns-topic"
}

To configure an SNS topic, use the event_hooks array and Update App Settings method:

// Note: Any previously existing hooks not included in event_hooks array will be deleted.
// Get current settings first to preserve your existing configuration.

// STEP 1: Get current app settings to preserve existing hooks
var settings = await client.GetAppAsync();
var existingHooks = settings.Data.App.EventHooks ?? new List<EventHook>();
Console.WriteLine($"Current event hooks: {existingHooks}");

// STEP 2: Add SNS hook while preserving existing hooks
var newSNSHook = new EventHook
{
    HookType = "sns",
    Enabled = true,
    EventTypes = new List<string>(), // empty list = all events
    SnsTopicArn = "arn:aws:sns:us-east-1:123456789012:sns-topic",
    SnsRegion = "us-east-1",
    SnsAuthType = "keys", // or "resource" for role-based auth
    SnsKey = "yourkey",
    SnsSecret = "yoursecret",
};

// STEP 3: Update with complete array including existing hooks
var allHooks = new List<EventHook>(existingHooks) { newSNSHook };
await client.UpdateAppAsync(new UpdateAppRequest
{
    EventHooks = allHooks,
});

// Test the SNS connection
await client.CheckSNSAsync(new CheckSNSRequest
{
    SnsKey = "yourkey",
    SnsSecret = "yoursecret",
    SnsTopicArn = "arn:aws:sns:us-east-1:123456789012:sns-topic",
});

Configuration Options

The following options are available when configuring an SNS event hook:

OptionTypeDescriptionRequired
idstringUnique identifier for the event hookNo. If empty, it will generate an ID.
enabledbooleanBoolean flag to enable/disable the hookYes
hook_typestringMust be set to "sns"Yes
sns_topic_arnstringThe AWS SNS topic ARNYes
sns_regionstringThe AWS region where the SNS topic is located (e.g., "us-east-1")Yes
sns_auth_typestringAuthentication type: "keys" for access key/secret or "resource" for role-based authYes
sns_keystringAWS access key ID (required if auth_type is "keys")Yes if using key auth
sns_secretstringAWS secret access key (required if auth_type is "keys")Yes if using key auth
event_typesarrayArray of event types this hook should handleNo. Not provided or empty array means subscribe to all existing and future events.

Payload Compression

SNS honours the same enable_hook_payload_compression flag — see the webhooks overview for enablement and the production checklist. When compression is on, the notification Message is gzipped + base64-encoded (SNS only accepts UTF-8) and the producer sets these message attributes:

{
  "content_encoding": "gzip",
  "content_type": "application/json",
  "payload_encoding": "base64"
}

Reading notifications from SNS

Call parseSns on your chat client with the notification body (either the raw envelope JSON string or the pre-extracted Message field) — it unwraps the SNS envelope when needed, reverses the base64 + gzip payload, and returns a typed event. The return shape matches verifyAndParseWebhook sans verification (see the overview for the per-language note on typed vs parsed-JSON output). The same call works whether or not compression is on, and whether the topic is delivered over HTTP or via an SQS subscription.

No Stream X-Signature on SNS. Stream does not ship an app-level HMAC on SNS payloads. SNS itself is authenticated with AWS signatures (SigningCertURL / Signature) when you subscribe over HTTPS.

HTTP subscribers receive one JSON envelope per POST; forwarded-through-SQS workers usually parse JSON and pass Message or the full inner document. Either form works — parse_sns detects and unwraps the envelope when needed.

var ev = client.ParseSns(notification.Message);

Where each argument comes from

ArgumentSourceExample
notificationBodyThe raw SNS HTTP envelope JSON, or the pre-extracted Message field (UTF-8 string)requestBody / notification.Message

parse_sns takes only the notification body string. No HMAC is involved; use your API secret only for other chat API calls.

Need a stateless helper? The same unwrap + decode + parse logic is exposed as a static / module-level parse_sns (see the webhooks overview for per-language imports). Use it in workers that don't keep a chat client around.

Building this without a Stream SDK? Expand the per-language reference implementation below.

Enabling compression and the production checklist are documented on the webhooks overview — the same enable_hook_payload_compression flag covers SNS.

SNS Best practices and Assumptions

  • Set the maximum message size set to 256 KB.

Messages bigger than the maximum message size will be dropped.