diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js
index 829573fe495b6ea234c242d05c9244282cb17650..822deedd5cc165c3149ea12758110ab7fc3e9bf8 100644
--- a/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js
@@ -3,10 +3,11 @@ import handleGroupChatsMsgs from './handlers/groupChatsMsgs';
 import handleGroupChatMsgBroadcast from './handlers/groupChatMsgBroadcast';
 import handleClearPublicGroupChat from './handlers/clearPublicGroupChat';
 import handleUserTyping from './handlers/userTyping';
+import handleSyncGroupChatMsg from './handlers/syncGroupsChat';
 import { processForHTML5ServerOnly } from '/imports/api/common/server/helpers';
 
-RedisPubSub.on('GetGroupChatMsgsRespMsg', processForHTML5ServerOnly(handleGroupChatsMsgs));
+RedisPubSub.on('GetGroupChatMsgsRespMsg', processForHTML5ServerOnly(handleSyncGroupChatMsg));
 RedisPubSub.on('GroupChatMessageBroadcastEvtMsg', handleGroupChatMsgBroadcast);
 RedisPubSub.on('ClearPublicChatHistoryEvtMsg', handleClearPublicGroupChat);
-RedisPubSub.on('SyncGetGroupChatMsgsRespMsg', handleGroupChatsMsgs);
+RedisPubSub.on('SyncGetGroupChatMsgsRespMsg', handleSyncGroupChatMsg);
 RedisPubSub.on('UserTypingEvtMsg', handleUserTyping);
diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/groupChatMsgBroadcast.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/groupChatMsgBroadcast.js
index 2e0340f5ea60114b58c2450372247983e2d8e0f5..dd116b6ecbd973ad0a67b2f77e00dc15510bf08d 100644
--- a/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/groupChatMsgBroadcast.js
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/groupChatMsgBroadcast.js
@@ -1,5 +1,13 @@
 import { check } from 'meteor/check';
+import _ from 'lodash';
 import addGroupChatMsg from '../modifiers/addGroupChatMsg';
+import addBulkGroupChatMsgs from '../modifiers/addBulkGroupChatMsgs';
+
+const { bufferChatInsertsMs } = Meteor.settings.public.chat;
+
+const msgBuffer = [];
+
+const bulkFn = _.throttle(addBulkGroupChatMsgs, bufferChatInsertsMs);
 
 export default function handleGroupChatMsgBroadcast({ body }, meetingId) {
   const { chatId, msg } = body;
@@ -8,5 +16,10 @@ export default function handleGroupChatMsgBroadcast({ body }, meetingId) {
   check(chatId, String);
   check(msg, Object);
 
-  addGroupChatMsg(meetingId, chatId, msg);
+  if (bufferChatInsertsMs) {
+    msgBuffer.push({ meetingId, chatId, msg });
+    bulkFn(msgBuffer);
+  } else {
+    addGroupChatMsg(meetingId, chatId, msg);
+  }
 }
diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/syncGroupsChat.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/syncGroupsChat.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb0f35437055904d9c45ca92ddcc93ebad98dea7
--- /dev/null
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/handlers/syncGroupsChat.js
@@ -0,0 +1,12 @@
+import { Match, check } from 'meteor/check';
+import addBulkGroupChatMsgs from '../modifiers/addBulkGroupChatMsgs';
+
+export default function handleSyncGroupChat({ body }, meetingId) {
+  const { chatId, msgs } = body;
+
+  check(meetingId, String);
+  check(chatId, String);
+  check(msgs, Match.Maybe(Array));
+
+  addBulkGroupChatMsgs(msgs);
+}
diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/modifiers/addBulkGroupChatMsgs.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/modifiers/addBulkGroupChatMsgs.js
new file mode 100644
index 0000000000000000000000000000000000000000..a51d75be39f6aea89ee33986e05bfe91d8ecc301
--- /dev/null
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/modifiers/addBulkGroupChatMsgs.js
@@ -0,0 +1,29 @@
+import { Match, check } from 'meteor/check';
+import { GroupChatMsg } from '/imports/api/group-chat-msg';
+import Logger from '/imports/startup/server/logger';
+import flat from 'flat';
+import { parseMessage } from './addGroupChatMsg';
+
+export default async function addBulkGroupChatMsgs(msgs) {
+  const mappedMsgs = msgs
+    .map(({ chatId, meetingId, msg }) => ({
+      _id: new Mongo.ObjectID()._str,
+      ...msg,
+      meetingId,
+      chatId,
+      message: parseMessage(msg.message),
+      sender: msg.sender.id,
+    }))
+    .map(el => flat(el, { safe: true }));
+
+  try {
+    const { insertedCount } = await GroupChatMsg.rawCollection().insertMany(mappedMsgs);
+    msgs.length = 0;
+
+    if (insertedCount) {
+      Logger.info(`Inserted ${insertedCount} messages`);
+    }
+  } catch (err) {
+    Logger.error(`Error on bulk insert. ${err}`);
+  }
+}
diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/modifiers/addGroupChatMsg.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/modifiers/addGroupChatMsg.js
index 9c4eac369ea30a2804689faa3c03492f6c34885d..e0f9a8d55d8e0668cff583003e67fe0ef3a80690 100644
--- a/bigbluebutton-html5/imports/api/group-chat-msg/server/modifiers/addGroupChatMsg.js
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/modifiers/addGroupChatMsg.js
@@ -4,7 +4,7 @@ import Logger from '/imports/startup/server/logger';
 import { GroupChatMsg } from '/imports/api/group-chat-msg';
 import { BREAK_LINE } from '/imports/utils/lineEndings';
 
-const parseMessage = (message) => {
+export function parseMessage(message) {
   let parsedMessage = message || '';
 
   // Replace \r and \n to <br/>
@@ -15,7 +15,7 @@ const parseMessage = (message) => {
   parsedMessage = parsedMessage.split('<a href="event:').join('<a target="_blank" href="');
 
   return parsedMessage;
-};
+}
 
 export default function addGroupChatMsg(meetingId, chatId, msg) {
   check(meetingId, String);
@@ -37,25 +37,15 @@ export default function addGroupChatMsg(meetingId, chatId, msg) {
     sender: msg.sender.id,
   };
 
-  const selector = {
-    meetingId,
-    chatId,
-    id: msg.id,
-  };
-
-  const modifier = {
-    $set: flat(msgDocument, { safe: true }),
-  };
+  const modifier = flat(msgDocument, { safe: true });
 
   try {
-    const { insertedId } = GroupChatMsg.upsert(selector, modifier);
+    const insertedId = GroupChatMsg.insert(modifier);
 
     if (insertedId) {
       Logger.info(`Added group-chat-msg msgId=${msg.id} chatId=${chatId} meetingId=${meetingId}`);
-    } else {
-      Logger.info(`Upserted group-chat-msg msgId=${msg.id} chatId=${chatId} meetingId=${meetingId}`);
     }
   } catch (err) {
-    Logger.error(`Adding group-chat-msg to collection: ${err}`);
+    Logger.error(`Error on adding group-chat-msg to collection: ${err}`);
   }
 }
diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml
index 62c69a3f6aa3fae15ab8fa27f9339c75ad666bfc..92b6aa661c4b4d4405250c9d08ae011695a84d05 100755
--- a/bigbluebutton-html5/private/config/settings.yml
+++ b/bigbluebutton-html5/private/config/settings.yml
@@ -244,6 +244,7 @@ public:
     time: 5000
   chat:
     enabled: true
+    bufferChatInsertsMs: 0
     startClosed: false
     min_message_length: 1
     max_message_length: 5000