In our scalable AWS serverless application (DynamoDB, Lambda, API Gateway WebSockets) we want to broadcast messages from a Lambda to very many connected browser sessions simultaneously.
We have many topics, and to limit the load on the system we want to limit each browser session to subscribe to max. two topics.
The AWS example app linked in this official tutorial does this by looping through the connectionIds and doing an await postToConnection for each of them, which doesn't scale well as each postToConnection takes 40 ms (average):
const AWS = require('aws-sdk');
const ddb = new AWS.DynamoDB.DocumentClient();
exports.handler = async function (event, context) {
let connections;
try {
connections = await ddb.scan({ TableName: process.env.table }).promise();
} catch (err) {
return {
statusCode: 500,
};
}
const callbackAPI = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint:
event.requestContext.domainName + '/' + event.requestContext.stage,
});
const message = JSON.parse(event.body).message;
const sendMessages = connections.Items.map(async ({ connectionId }) => {
if (connectionId !== event.requestContext.connectionId) {
try {
await callbackAPI
.postToConnection({ ConnectionId: connectionId, Data: message })
.promise();
} catch (e) {
console.log(e);
}
}
});
try {
await Promise.all(sendMessages);
} catch (e) {
console.log(e);
return {
statusCode: 500,
};
}
return { statusCode: 200 };
};
How can we make this broadcast scalable?