This functionality is available starting from Aidbox version 2602.

Objectives

Before you begin

  • Make sure your Aidbox version is 2602 or newer
  • Setup the local Aidbox instance using getting started guide

What is AWS SNS?

AWS SNS is a fully managed pub/sub messaging service that enables you to decouple microservices, distributed systems, and event-driven serverless applications. SNS delivers messages to subscribers using a push-based model, supporting protocols such as HTTP/S, email, SMS, SQS, Lambda, and more.

For detailed information, see the official SNS documentation .

Key Concepts

Topic is a communication channel for publishing messages. Publishers send messages to a topic, and SNS delivers them to all subscribers.

Subscription connects a topic to an endpoint (SQS queue, Lambda, HTTP/S, email, SMS). Each subscription receives a copy of every message published to the topic.

FIFO Topics provide strict message ordering and exactly-once delivery. FIFO topic names end with .fifo and require a messageGroupId for each message.

Best Effort vs At-Least-Once Delivery

In Aidbox, two AidboxTopicDestination profiles are supported:

  • http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-sns-best-effort — Events are sent immediately. If SNS returns an error, the event is lost. Low latency, suitable for non-critical notifications.
  • http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-sns-at-least-once — Events are persisted to database before sending. If SNS is unavailable, events remain in queue and are retried automatically. Supports batching up to 10 events. Guaranteed delivery for critical integrations.

Setting up locally

Follow the steps to try AWS SNS AidboxTopicSubscription with LocalStack — a local AWS emulator for development and testing.

1. Create directory structure

mkdir sns-tutorial && cd sns-tutorial

2. Configure docker-compose.yaml

Download the getting started docker-compose.yaml and add LocalStack service for local testing:

services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - "4566:4566"
    environment:
      - SERVICES=sns,sqs
      - DEBUG=1

  aidbox:
    # ... existing aidbox configuration ...
    volumes:
      - ./topic-destination-sns-2602.1.jar:/topic-destination-sns.jar
    environment:
      BOX_MODULE_LOAD: io.healthsamurai.topic-destination.sns.core
      BOX_MODULE_JAR: "/topic-destination-sns.jar"
      # ... other envs ...

3. Download the SNS module

Download .jar SNS module file from our bucket and place it next to docker-compose.yaml.

curl -O https://storage.googleapis.com/aidbox-modules/topic-destination-aws-sns/topic-destination-sns-2602.1.jar

4. Start services

docker compose up -d

5. Verify installation

In AidboxUI, go to FHIR Packages -> io.health-samurai.core.r4#0.0.0-snapshot and make sure that SNS profiles are present:

  • aidboxtopicdestination-aws-sns-best-effort
  • aidboxtopicdestination-aws-sns-at-least-once

6. Create SNS topic and SQS subscriber in LocalStack

Since SNS is a push-based service, we need a subscriber to verify messages are delivered. Create an SNS topic, an SQS queue, and subscribe the queue to the topic:

aws --endpoint-url=http://localhost:4566 sns create-topic \
  --name patient-events \
  --region us-east-1
aws --endpoint-url=http://localhost:4566 sqs create-queue \
  --queue-name patient-events-queue \
  --region us-east-1
aws --endpoint-url=http://localhost:4566 sns subscribe \
  --topic-arn arn:aws:sns:us-east-1:000000000000:patient-events \
  --protocol sqs \
  --notification-endpoint arn:aws:sqs:us-east-1:000000000000:patient-events-queue \
  --region us-east-1

Basic Usage (Best Effort)

1. Create a subscription topic

POST /fhir/AidboxSubscriptionTopic
content-type: application/json
accept: application/json

{
  "resourceType": "AidboxSubscriptionTopic",
  "url": "patient-topic",
  "status": "active",
  "trigger": [
    {
      "resource": "Patient",
      "fhirPathCriteria": "name.exists()"
    }
  ]
}

2. Create AidboxTopicDestination

POST /fhir/AidboxTopicDestination
content-type: application/json
accept: application/json

{
  "id": "sns-destination",
  "resourceType": "AidboxTopicDestination",
  "meta": {
    "profile": [
      "http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-sns-best-effort"
    ]
  },
  "kind": "aws-sns-best-effort",
  "topic": "patient-topic",
  "parameter": [
    {
      "name": "topicArn",
      "valueString": "arn:aws:sns:us-east-1:000000000000:patient-events"
    },
    {
      "name": "region",
      "valueString": "us-east-1"
    },
    {
      "name": "accessKeyId",
      "valueString": "test"
    },
    {
      "name": "secretAccessKey",
      "valueString": "test"
    },
    {
      "name": "endpointOverride",
      "valueString": "http://localstack:4566"
    }
  ]
}

3. Create a Patient

POST /fhir/Patient
content-type: application/json

{
  "name": [{"family": "Smith", "given": ["John"]}]
}

4. Verify event delivery

Check the topic destination status:

GET /fhir/AidboxTopicDestination/sns-destination/$status

View events in LocalStack

Read messages from the SQS queue:

aws --endpoint-url=http://localhost:4566 sqs receive-message \
  --queue-url http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/patient-events-queue \
  --region us-east-1

The response contains an SNS notification envelope in the Body field:

{
    "Messages": [
        {
            "MessageId": "e6e85c6c-9d6f-411e-90f5-76c770a3efb6",
            "ReceiptHandle": "YzExNjA4Y...",
            "MD5OfBody": "823410b8aba2ce106f19e73407788854",
            "Body": "<json>"
        }
    ]
}

Extract the FHIR notification Bundle from the SNS envelope using jq:

aws --endpoint-url=http://localhost:4566 sqs receive-message \
  --queue-url http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/patient-events-queue \
  --region us-east-1 \
  | jq -r '.Messages[0].Body | fromjson | .Message | fromjson'

At-Least-Once Delivery

For guaranteed delivery with batch processing, use the at-least-once profile:

POST /fhir/AidboxTopicDestination
content-type: application/json
accept: application/json

{
  "id": "sns-reliable",
  "resourceType": "AidboxTopicDestination",
  "meta": {
    "profile": [
      "http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-sns-at-least-once"
    ]
  },
  "kind": "aws-sns-at-least-once",
  "topic": "patient-topic",
  "parameter": [
    {
      "name": "topicArn",
      "valueString": "arn:aws:sns:us-east-1:000000000000:patient-events"
    },
    {
      "name": "region",
      "valueString": "us-east-1"
    },
    {
      "name": "accessKeyId",
      "valueString": "test"
    },
    {
      "name": "secretAccessKey",
      "valueString": "test"
    },
    {
      "name": "endpointOverride",
      "valueString": "http://localstack:4566"
    },
    {
      "name": "batchSize",
      "valueInteger": 10
    }
  ]
}

The batchSize parameter (1-10) controls how many events are sent in a single PublishBatch API call. SNS allows maximum 10 entries per request .

Configuration Reference

Available Parameters

ParameterTypeRequiredDescription
topicArnvalueStringYesSNS topic ARN (arn:aws:sns:us-east-1:123456789012:my-topic)
regionvalueStringYesAWS region (us-east-1, eu-west-1, etc.)
accessKeyIdvalueStringNoAWS Access Key ID (uses default credential chain if not provided)
secretAccessKeyvalueStringNoAWS Secret Access Key
endpointOverridevalueStringNoOverride endpoint URL (for LocalStack: http://localstack:4566)
messageGroupIdvalueStringNoMessage group ID for FIFO SNS topics (required for .fifo topics)
batchSizevalueIntegerNoEvents per batch, 1-10 (at-least-once only, default: 1)

Message Format

Messages published to SNS have this structure:

{
  "topic": "patient-topic",
  "value": {
    "resourceType": "Bundle",
    "type": "history",
    "timestamp": "2026-02-18T07:48:19Z",
    "entry": [
      {
        "resource": {
          "resourceType": "AidboxSubscriptionStatus",
          "status": "active",
          "type": "event-notification",
          "notificationEvent": [
            {
              "eventNumber": 1,
              "focus": { "reference": "Patient/7d9388ae-9f0e-437a-a055-cc3129f7f5b9" }
            }
          ],
          "topic": "patient-topic",
          "topic-destination": {
            "reference": "AidboxTopicDestination/sns-destination"
          }
        }
      },
      {
        "request": { "method": "POST", "url": "/fhir/Patient" },
        "fullUrl": "http://localhost:8080/fhir/Patient/7d9388ae-9f0e-437a-a055-cc3129f7f5b9",
        "resource": {
          "resourceType": "Patient",
          "id": "7d9388ae-9f0e-437a-a055-cc3129f7f5b9",
          "name": [{ "given": ["John"], "family": "Smith" }]
        }
      }
    ]
  }
}

AWS Authentication

Option 1: Access Keys (for development)

Provide accessKeyId and secretAccessKey parameters directly in the AidboxTopicDestination.

When running on AWS (EC2, ECS, EKS), omit accessKeyId and secretAccessKey. The module will use the default AWS credential chain:

  1. 1.
    Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
  2. 2.
    Web Identity Token (for EKS)
  3. 3.
    EC2/ECS Instance Profile

Required IAM permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:*:*:your-topic-name"
    }
  ]
}

Monitoring

Status Endpoint

GET /fhir/AidboxTopicDestination/{id}/$status

Response Parameters

ParameterDescription
messagesDeliveredTotal successfully delivered events
messagesDeliveryAttemptsFailed delivery attempts
messagesInProcessEvents currently being sent
messagesQueuedEvents waiting in queue (at-least-once only)
startTimestampDestination start time
statusAlways active
lastErrorDetailRecent error information

Prometheus Metrics

GET /metrics

Metrics include:

  • aidbox_topic_destination_messages_delivered
  • aidbox_topic_destination_messages_queued
  • aidbox_topic_destination_messages_in_process

Set up with AWS

Prerequisites

  1. 1.
    AWS account with SNS access
  2. 2.
    AWS CLI configured: aws configure
  3. 3.
    IAM user/role with sns:Publish permission

Step 1: Create SNS Topic

aws sns create-topic --name aidbox-events --region us-east-1

Step 2: Create SQS Queue for Testing

Create a queue to receive events (for verification):

aws sqs create-queue --queue-name aidbox-test-queue --region us-east-1

Step 3: Subscribe SQS to SNS

SNS_ARN=arn:aws:sns:us-east-1:YOUR_ACCOUNT_ID:aidbox-events

SQS_ARN=$(aws sqs get-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/YOUR_ACCOUNT_ID/aidbox-test-queue \
  --attribute-names QueueArn \
  --query 'Attributes.QueueArn' \
  --output text \
  --region us-east-1)
aws sns subscribe \
  --topic-arn $SNS_ARN \
  --protocol sqs \
  --notification-endpoint $SQS_ARN \
  --region us-east-1

Step 4: Configure SQS Policy

Allow SNS to send messages to SQS:

aws sqs set-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/YOUR_ACCOUNT_ID/aidbox-test-queue \
  --attributes '{
    "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"sns.amazonaws.com\"},\"Action\":\"sqs:SendMessage\",\"Resource\":\"arn:aws:sqs:us-east-1:YOUR_ACCOUNT_ID:aidbox-test-queue\"}]}"
  }' \
  --region us-east-1

Step 5: Create AidboxTopicDestination

When running on AWS infrastructure (EC2, ECS, EKS), use IAM roles instead of access keys. See AWS Authentication for details.

POST /fhir/AidboxTopicDestination
content-type: application/json

{
  "id": "sns-aws",
  "resourceType": "AidboxTopicDestination",
  "meta": {
    "profile": [
      "http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-sns-at-least-once"
    ]
  },
  "kind": "aws-sns-at-least-once",
  "topic": "patient-topic",
  "parameter": [
    {"name": "topicArn", "valueString": "arn:aws:sns:us-east-1:YOUR_ACCOUNT_ID:aidbox-events"},
    {"name": "region", "valueString": "us-east-1"}
  ]
}

Step 6: Test and Verify

  1. 1.
    Create a Patient in Aidbox (see Basic Usage above)
  2. 2.
    Open the Amazon SQS console, select your queue, and click Send and receive messages
  3. 3.
    In the Receive messages section, click Poll for messages
SQS console showing a received SNS notification after polling

Polling for messages in the SQS queue subscribed to the SNS topic

  1. 4.
    Click on a message to view its contents — the Body contains the SNS notification envelope with the FHIR Bundle:
SQS message body showing the FHIR notification Bundle delivered via SNS

SNS notification containing the FHIR event Bundle with Patient resource

You can also verify via CLI:

aws sqs receive-message \
  --queue-url https://sqs.us-east-1.amazonaws.com/YOUR_ACCOUNT_ID/aidbox-test-queue \
  --region us-east-1

Aidbox

AWS SNS

Last updated: