vintasend-aws-sqs
v0.13.3
Published
AWS SQS queue services for VintaSend notification dispatch and replication workflows.
Downloads
2,158
Readme
VintaSend AWS SQS Queue Services
AWS SQS queue services for VintaSend notification dispatch and replication workflows.
Installation
npm install vintasend-aws-sqsWhat this package provides
AwsSqsNotificationQueueService: enqueues notification IDs to a notifications queueAwsSqsReplicationQueueService: enqueues notification IDs + backend identifiers to a replication queue
Both services send JSON message bodies and are compatible with Lambda SQS triggers.
Message contracts
Notification queue message
{
"notificationId": "notification-123"
}Replication queue message
{
"notificationId": "notification-123",
"backendIdentifier": "replica-backend"
}Basic usage
import {
AwsSqsNotificationQueueService,
AwsSqsReplicationQueueService,
} from 'vintasend-aws-sqs';
const notificationQueueService = new AwsSqsNotificationQueueService({
queueUrl: process.env.NOTIFICATION_QUEUE_URL!,
sqsClientConfig: { region: process.env.AWS_REGION ?? 'us-east-1' },
});
const replicationQueueService = new AwsSqsReplicationQueueService({
queueUrl: process.env.REPLICATION_QUEUE_URL!,
sqsClientConfig: { region: process.env.AWS_REGION ?? 'us-east-1' },
});Terraform examples
This package includes three Terraform examples:
examples/terraform/notifications-queue.tfexamples/terraform/replication-queue.tfexamples/terraform/eventbridge-send-pending-notifications.tf
Each file creates:
- Primary SQS queue
- DLQ
- Redrive policy with configurable retry attempts (
maxReceiveCount) - Lambda event source mapping (
aws_lambda_event_source_mapping) - Useful queue outputs
1) Notifications queue + Lambda trigger
Use examples/terraform/notifications-queue.tf and provide:
- Optional
notification_lambda_function_name: Lambda name that sends notifications - Optional queue tuning values (
notification_batch_size, batching window) - Optional retry tuning with
notification_max_receive_count(default:5)
2) Replication queue + Lambda trigger
Use examples/terraform/replication-queue.tf and provide:
- Optional
replication_lambda_function_name: Lambda name that performs replication to the target backend - Optional queue tuning values (
replication_batch_size, batching window) - Optional retry tuning with
replication_max_receive_count(default:5)
3) EventBridge schedule for periodic sendPendingNotifications
Use examples/terraform/eventbridge-send-pending-notifications.tf and provide:
send_pending_notifications_lambda_function_name: Lambda name that callssendPendingNotifications- Optional
schedule_expression(default:rate(1 minute)) - Optional EventBridge target retry tuning:
eventbridge_target_maximum_retry_attempts(default:5)eventbridge_target_maximum_event_age_in_seconds(default:3600)
Example apply flow
cd examples/terraform
terraform init
# Create both queues only (no Lambda trigger wiring)
terraform apply \
-var="project=my-app" \
-var="environment=prod"
# Create queues and wire notification Lambda trigger
terraform apply \
-var="notification_lambda_function_name=vintasend-notification-sender" \
-var="notification_max_receive_count=8" \
-var="project=my-app" \
-var="environment=prod"
# Create queues and wire replication Lambda trigger
terraform apply \
-var="replication_lambda_function_name=vintasend-replication-worker" \
-var="replication_max_receive_count=8" \
-var="project=my-app" \
-var="environment=prod"
# Create EventBridge schedule to trigger sendPendingNotifications periodically
terraform apply \
-var="send_pending_notifications_lambda_function_name=vintasend-send-pending-notifications" \
-var="schedule_expression=rate(5 minutes)" \
-var="eventbridge_target_maximum_retry_attempts=8" \
-var="project=my-app" \
-var="environment=prod"Lambda consumer setup
You typically run two Lambda consumers:
- Notification sender Lambda
- Replication worker Lambda
Both are triggered by SQS through event source mappings created in Terraform.
Notification sender Lambda (example)
import type { SQSEvent, SQSBatchResponse } from 'aws-lambda';
import { getNotificationService } from 'lib/notification-service';
interface NotificationQueueMessage {
notificationId: string;
}
export const handler = async (event: SQSEvent): Promise<SQSBatchResponse> => {
const failures: { itemIdentifier: string }[] = [];
await Promise.all(
event.Records.map(async (record) => {
try {
const payload = JSON.parse(record.body) as NotificationQueueMessage;
// Call your VintaSend send operation here
const vintasend = getNotificationService();
const notification = vintaSend.getNotification(payload.notificationId);
await vintasend.send(notification);
} catch {
failures.push({ itemIdentifier: record.messageId });
}
}),
);
return { batchItemFailures: failures };
};Replication worker Lambda (example)
import type { SQSEvent, SQSBatchResponse } from 'aws-lambda';
import { getNotificationService } from 'lib/notification-service';
interface ReplicationQueueMessage {
notificationId: string;
backendIdentifier: string;
}
export const handler = async (event: SQSEvent): Promise<SQSBatchResponse> => {
const failures: { itemIdentifier: string }[] = [];
await Promise.all(
event.Records.map(async (record) => {
try {
const payload = JSON.parse(record.body) as ReplicationQueueMessage;
// Call your replication operation here
const vintasend = getNotificationService();
await vintasend.processReplication(payload.notificationId, payload.backendIdentifier);
} catch {
failures.push({ itemIdentifier: record.messageId });
}
}),
);
return { batchItemFailures: failures };
};Periodic pending notifications Lambda (EventBridge example)
import type { EventBridgeEvent } from 'aws-lambda';
import { getNotificationService } from 'lib/notification-service';
export const handler = async (
_event: EventBridgeEvent<string, unknown>,
): Promise<{ ok: true }> => {
const vintasend = getNotificationService();
await vintasend.sendPendingNotifications();
return { ok: true };
};This Lambda is invoked by EventBridge and should call sendPendingNotifications() once per schedule tick.
Required Lambda IAM permissions
Your Lambda execution roles need SQS consumer permissions for their respective queues:
sqs:ReceiveMessagesqs:DeleteMessagesqs:ChangeMessageVisibilitysqs:GetQueueAttributessqs:GetQueueUrl
Operational notes
- Keep queue
visibility_timeout_secondsgreater than Lambda timeout. - Use DLQ monitoring and alarms for failed messages.
- Use idempotent handlers to safely handle retries.
- Keep batch size aligned with downstream throughput.
- Tune retries with
notification_max_receive_countandreplication_max_receive_countbased on transient failure patterns.
License
MIT
