title: AWS Lambda SNS sending topic twice
body: <h2>TL;DR</h2>
  
  <p>Writing a lambda function to perform some DB queries and then email certain groups of users.</p>
  
  <ul>
  <li>publish SNS message for every group the song is shared to</li>
  <li>Each group has it's own members, thus it's own set of emails</li>
  <li>SNS topics get sent twice for each group.</li>
  </ul>
  
  <p>Members are receiving the email twice.</p>
  
  <p>The app is a music streaming app where users can create songs. They can also create groups, invite members to those groups and share their songs to these groups.</p>
  
  <p>Here is the lambda called via API: </p>
  
  <pre><code>  const shareWithGroup = async event =&gt; {
    const { songCuid, groupCuids } = JSON.parse(event.body);
    const shareSongDB = await query(
      sql.queryShareWithGroup(songCuid, groupCuids),
    ); //share to group in DB
    if (!shareSongDB) {
      return corsUtil.failureWithCors("Couldn't Share Song with group");
    }
    const song = await query(sql.queryRead(songCuid));
    if (!song) {
      return corsUtil.failureWithCors('Song doesnt exist');
    }
    const songTitle = song.rows[0].songTitle; //retrieve songTitle
    const promises = groupCuids.map(async groupCuid =&gt; {
      console.log('GROUP_CUID', groupCuid);
      const emailResults = await query(sql.queryReadGroupEmails(groupCuid)); // get emails for group + groupName
      const results = emailResults.rows;
      const groupName = results[0].groupName;
      let emails = [];
      results.map(row =&gt; {
        emails.push(row.email); //push email address into array
      });
      const payload = JSON.stringify({ groupName, emails, songTitle }); //send groupName, emails list and songTitle to SNS to trigger email
      console.log(payload);
      await publishSNS(payload)
      //send the topic
    });
  
    //Resolve all promises
    await Promise.all(promises);
    console.log(promises);
    return corsUtil.successWithCors('Success');
  };
  
  const publishSNS = async payload =&gt; {
    console.log('publishing sns topic');
    //SEND EMAILS
    const params = {
      Message: payload,
      TopicArn: `arn:aws:sns:eu-west-1:${process.env.AWS_ACC_ID}:${process.env.STAGE}-songShareTrigger`,
    };
  
    return await sns
      .publish(params, async error =&gt; {
        if (error) {
          console.error(error);
          //TODO: Actually fail the function - can't do with lambdaFactory
        }
      })
      .promise();
  };
  </code></pre>
  
  <p>And a sample request (share a song to 1 group):</p>
  
  <pre><code>{"songCuid":"XXX","groupCuids":["XXX"]}
  </code></pre>
  
  <p>The issue is, that somehow, even though it should only send 1 SNS topic, it sends 2. When I share a song to 2 groups, it sends 4 SNS topics.</p>
  
  <p>Here is the lambda that is triggered by the SNS topic:</p>
  
  <pre><code>const aws = require('aws-sdk');
  const ses = new aws.SES();
  const corsUtil = require('../utils/corsUtil');
  
  exports.songShareEmail = (event, context) =&gt; {
    console.log('EVENT : ', event.Records[0].Sns); // LOG SNS
    const body = JSON.parse(event.Records[0].Sns.Message);
    const { groupName, emails, songTitle } = body;
    console.log('Body : ', body);
  
    const groupInviteEmailData = `
        &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
        &lt;html&gt;
        &lt;head&gt;
          &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
          &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"/&gt;
        &lt;/head&gt;
        &lt;body&gt;
          &lt;div class="email-body" style="max-width:900px; margin:auto;" &gt;
            &lt;div class="content" style="background-color:white; margin:0 auto; 
              display:block;"&gt;
              &lt;p&gt;Hello&lt;p&gt;
              &lt;/br&gt;
              A new song has been shared to the group : &lt;u&gt;${groupName}&lt;/u&gt;&lt;br&gt;
              &lt;h3&gt;Song Title: ${songTitle}&lt;/h3&gt;
  
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/body&gt;
        &lt;/html&gt;
    `;
  
      var params = {
          Destination: {
            ToAddresses: emails,
          },
          Message: {
            Body: {
              Html: {
                Charset: 'UTF-8',
                Data: groupInviteEmailData,
              },
            },
            Subject: {
              Charset: 'UTF-8',
              Data: `New song shared to ${groupName}`,
            },
          },
          Source: 'xxx',
        };
        console.log('sendingEmail');
        ses.sendEmail(params, function(err) {
          if (err) {
            console.log(err);
            const response = corsUtil.failureWithCors(err);
            context.fail(response);
          } else {
            context.succeed('Done');
          }
        });
      };
  </code></pre>
  
  <p>I have logged the SNS object from the event, and I can see that it is a new MessageId each time meaning that it is in fact sending 2 topics each time, and it's not that the lambda is getting triggered twice from the same SNS.</p>
  
  <p>Is there any way around this? </p>