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)
| Variable | Default | Purpose |
|---|---|---|
AWS_SNS_BOOKING_ANNOUNCEMENT_TOPIC_ID | arn:aws:sns:ap-south-1:910460496168:owner-instant-booking-announcement-sandbox | SNS topic we accept events from (rejects others; blank disables the check) |
WHATSAPP_ANNOUNCEMENT_SQS_QUEUE_NAME | whatsapp-booking-announcement-sandbox | SQS queue the @SqsListener consumes |
WHATSAPP_ANNOUNCEMENT_SQS_ENABLED | false | Turns the SQS consumer on (off by default so the app boots without AWS) |
AWS_REGION | ap-south-1 | AWS 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).
| Sandbox | Prod | |
|---|---|---|
| SNS topic | owner-instant-booking-announcement-sandbox | owner-instant-booking-announcement-prod |
| SQS queue | whatsapp-booking-announcement-sandbox | whatsapp-booking-announcement-prod |
| DLQ | …-sandbox-dlq | …-prod-dlq |
| Subscription | SQS, RawMessageDelivery=true | SQS, RawMessageDelivery=true |
IAM (on user/sdk) | whatsapp-booking-announcement-sqs-consume | whatsapp-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.