Skip to main content

Deployment & AWS Setup

What it takes to run WhatsApp Group Booking Announcements in an environment.

1. Database migration

Liquibase changeset 070-add-whatsapp-group-subscriptions.sql creates:

  • whatsapp_group_subscription — group ↔ property subscriptions (scoped by purpose)
  • whatsapp_group_announcement_log — idempotency + audit of sent announcements

It runs automatically with the standard Liquibase migration on deploy (includeAll changelog). It also depends on 069-add-whatsapp-groups.sql (the whatsapp_group table the subscription FK points at), so ensure WhatsApp Groups is already migrated.

2. Environment variables (admin-api)

VariableDefaultPurpose
AWS_SNS_BOOKING_ANNOUNCEMENT_TOPIC_IDarn:aws:sns:ap-south-1:910460496168:owner-instant-booking-announcement-sandboxSNS topic we accept events from (rejects others; blank disables the check)
WHATSAPP_ANNOUNCEMENT_SQS_QUEUE_NAMEwhatsapp-booking-announcement-sandboxSQS queue the @SqsListener consumes
WHATSAPP_ANNOUNCEMENT_SQS_ENABLEDfalseTurns the SQS consumer on (off by default so the app boots without AWS)
AWS_REGIONap-south-1AWS region

AWS credentials use the default provider chain (env / instance role / profile).

To enable the SQS path in an environment, set WHATSAPP_ANNOUNCEMENT_SQS_ENABLED=true.

3. AWS resources

The booking-announcement SNS topic is owned by innsync. For the SNS → SQS path, provision a queue, a DLQ, the access policy, and the subscription. Replace the names/ARNs per environment.

export TOPIC_ARN="arn:aws:sns:ap-south-1:910460496168:owner-instant-booking-announcement-sandbox"
export QUEUE="whatsapp-booking-announcement-sandbox"
export DLQ="whatsapp-booking-announcement-sandbox-dlq"

# DLQ + main queue (14-day retention; 60s visibility)
DLQ_URL=$(aws sqs create-queue --queue-name "$DLQ" \
--attributes MessageRetentionPeriod=1209600 --query QueueUrl --output text)
DLQ_ARN=$(aws sqs get-queue-attributes --queue-url "$DLQ_URL" \
--attribute-names QueueArn --query Attributes.QueueArn --output text)

Q_URL=$(aws sqs create-queue --queue-name "$QUEUE" \
--attributes VisibilityTimeout=60,MessageRetentionPeriod=1209600 --query QueueUrl --output text)
Q_ARN=$(aws sqs get-queue-attributes --queue-url "$Q_URL" \
--attribute-names QueueArn --query Attributes.QueueArn --output text)

# Queue policy (allow the SNS topic to SendMessage) + redrive to DLQ after 5 failures
# Build /tmp/attrs.json with {"Policy": "...", "RedrivePolicy": "..."} (stringified JSON values), then:
aws sqs set-queue-attributes --queue-url "$Q_URL" --attributes file:///tmp/attrs.json

# Subscribe the queue to the topic (raw delivery → SQS body is the booking JSON directly)
aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs \
--notification-endpoint "$Q_ARN" --attributes RawMessageDelivery=true

Queue access policy (Policy) — allow SNS to publish, scoped to the topic:

{ "Version": "2012-10-17", "Statement": [{
"Sid": "AllowSNSPublish", "Effect": "Allow",
"Principal": { "Service": "sns.amazonaws.com" },
"Action": "sqs:SendMessage", "Resource": "<QUEUE_ARN>",
"Condition": { "ArnEquals": { "aws:SourceArn": "<TOPIC_ARN>" } } }] }

Redrive policy (RedrivePolicy): {"deadLetterTargetArn":"<DLQ_ARN>","maxReceiveCount":"5"}.

IAM — app permission to consume

The admin-api principal needs to read the queue:

{ "Version": "2012-10-17", "Statement": [{
"Sid": "ConsumeBookingAnnouncementQueue", "Effect": "Allow",
"Action": ["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes",
"sqs:GetQueueUrl","sqs:ChangeMessageVisibility"],
"Resource": ["<QUEUE_ARN>","<DLQ_ARN>"] }] }

Attach to the IAM role/user the app runs as, e.g.:

aws iam put-user-policy --user-name <app-user> \
--policy-name whatsapp-booking-announcement-sqs-consume \
--policy-document file:///tmp/iam.json

Alternative: SNS → HTTPS (no SQS)

Subscribe the topic directly to the endpoint instead of a queue:

aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol https \
--notification-endpoint "https://<admin-api-host>/api/webhooks/booking-announcement"

The controller auto-confirms the subscription (it visits the SubscribeURL, but only for the configured topic). Note: this path has no durable buffer — an outage during delivery relies on SNS retries (configure a subscription DLQ if you use it in production). Prefer the SQS path for prod.

4. Verify

# Publish a test event and confirm it lands in the queue
aws sns publish --topic-arn "$TOPIC_ARN" --message '{"event":"BOOKING_CANCELLED","id":"TEST","propertyIds":["prop_123"]}'
aws sqs receive-message --queue-url "$Q_URL" --wait-time-seconds 10

Then create a subscription (POST .../groups/{groupId}/subscriptions) for a group whose propertyId matches, publish again, and confirm the group receives the message. Audit rows land in whatsapp_group_announcement_log; un-processable messages end up in the DLQ.

Provisioned resources

Sandbox and prod live in the same AWS account 910460496168 (region ap-south-1), distinguished by the -sandbox / -prod suffix. innsync publishes to the matching topic per environment (AWS_SNS_BOOKING_ANNOUNCEMENT_TOPIC_ID, sandbox by default, prod overridden in prod).

SandboxProd
SNS topicowner-instant-booking-announcement-sandboxowner-instant-booking-announcement-prod
SQS queuewhatsapp-booking-announcement-sandboxwhatsapp-booking-announcement-prod
DLQ…-sandbox-dlq…-prod-dlq
SubscriptionSQS, RawMessageDelivery=trueSQS, RawMessageDelivery=true
IAM (on user/sdk)whatsapp-booking-announcement-sqs-consumewhatsapp-booking-announcement-sqs-consume-prod

Both queues have a redrive policy to their DLQ (maxReceiveCount=5) and an access policy allowing only the matching SNS topic to publish. To enable a path, set WHATSAPP_ANNOUNCEMENT_SQS_ENABLED=true and point AWS_SNS_BOOKING_ANNOUNCEMENT_TOPIC_ID / WHATSAPP_ANNOUNCEMENT_SQS_QUEUE_NAME at that environment's topic/queue.