diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py
index a0b3713..5571564 100644
--- a/web/pgadmin/feature_tests/query_tool_tests.py
+++ b/web/pgadmin/feature_tests/query_tool_tests.py
@@ -96,6 +96,11 @@ class QueryToolFeatureTest(BaseFeatureTest):
         print("OK.", file=sys.stderr)
         self._clear_query_tool()
 
+        # Notify Statements.
+        print("Capture Notify Statements... ", file=sys.stderr, end="")
+        self._query_tool_notify_statements()
+        self._clear_query_tool()
+
     def after(self):
         self.page.remove_server(self.server)
         connection = test_utils.get_db_connection(
@@ -615,3 +620,50 @@ SELECT 1, pg_sleep(300)"""
             self.server['sslmode']
         )
         return connection.server_version > 90100
+
+    def _query_tool_notify_statements(self):
+        print("\n\tListen on an event... ", file=sys.stderr, end="")
+        self.page.fill_codemirror_area_with("LISTEN foo;")
+        self.page.find_by_id("btn-flash").click()
+        self.page.wait_for_query_tool_loading_indicator_to_disappear()
+        self.page.click_tab('Messages')
+        self.page.find_by_xpath(
+            '//div[contains(@class, "sql-editor-message") and '
+            'contains(string(), "LISTEN")]'
+        )
+        print("OK.", file=sys.stderr)
+        self._clear_query_tool()
+
+        wait = WebDriverWait(self.page.driver, 2)
+        print("\tNotify event without data... ", file=sys.stderr, end="")
+        self.page.fill_codemirror_area_with("NOTIFY foo;")
+        self.page.find_by_id("btn-flash").click()
+        self.page.wait_for_query_tool_loading_indicator_to_disappear()
+        self.page.click_tab('Notifications')
+        wait.until(EC.presence_of_element_located(
+            (By.XPATH, "//td[contains(@class,'channel') and "
+                       "contains(.,'foo')]"))
+        )
+        self.page.find_by_xpath(
+            '//td[contains(@class, "channel") and '
+            'contains(string(), "foo")]'
+        )
+        print("OK.", file=sys.stderr)
+        self._clear_query_tool()
+
+        print("\tNotify event with data... ", file=sys.stderr, end="")
+        self.page.fill_codemirror_area_with("SELECT pg_notify('foo', "
+                                            "'Hello')")
+        self.page.find_by_id("btn-flash").click()
+        self.page.wait_for_query_tool_loading_indicator_to_disappear()
+        self.page.click_tab('Notifications')
+        wait.until(EC.presence_of_element_located(
+            (By.XPATH, "//td[contains(@class,'payload') and "
+                       "contains(.,'Hello')]"))
+        )
+        self.page.find_by_xpath(
+            '//td[contains(@class, "payload") and '
+            'contains(string(), "Hello")]'
+        )
+        print("OK.", file=sys.stderr)
+        self._clear_query_tool()
diff --git a/web/pgadmin/static/js/sqleditor/execute_query.js b/web/pgadmin/static/js/sqleditor/execute_query.js
index 333a3a2..4f511fb 100644
--- a/web/pgadmin/static/js/sqleditor/execute_query.js
+++ b/web/pgadmin/static/js/sqleditor/execute_query.js
@@ -82,6 +82,8 @@ class ExecuteQuery {
           self.loadingScreen.hide();
           self.enableSQLEditorButtons();
           self.sqlServerObject.update_msg_history(false, httpMessageData.data.result);
+          if ('notifications' in httpMessageData.data)
+            self.sqlServerObject.update_notifications(httpMessageData.data.notifications);
 
           // Highlight the error in the sql panel
           self.sqlServerObject._highlight_error(httpMessageData.data.result);
@@ -116,6 +118,8 @@ class ExecuteQuery {
           self.loadingScreen.setMessage('Loading data from the database server and rendering...');
 
           self.sqlServerObject.call_render_after_poll(httpMessage.data.data);
+          if ('notifications' in httpMessage.data.data)
+            self.sqlServerObject.update_notifications(httpMessage.data.data.notifications);
         } else if (ExecuteQuery.isQueryStillRunning(httpMessage)) {
           // If status is Busy then poll the result by recursive call to the poll function
           this.delayedPoll();
diff --git a/web/pgadmin/static/js/sqleditor/query_tool_notifications.js b/web/pgadmin/static/js/sqleditor/query_tool_notifications.js
new file mode 100644
index 0000000..500d205
--- /dev/null
+++ b/web/pgadmin/static/js/sqleditor/query_tool_notifications.js
@@ -0,0 +1,131 @@
+import gettext from 'sources/gettext';
+import Backgrid from 'pgadmin.backgrid';
+import Backbone from 'backbone';
+import Alertify from 'pgadmin.alertifyjs';
+
+let NotificationsModel = Backbone.Model.extend({
+  defaults: {
+    recorded_time: undefined,
+    event: undefined,
+    pid: undefined,
+    payload: undefined,
+  },
+  schema: [{
+    id: 'recorded_time',
+    label: gettext('Recorded time'),
+    cell: 'string',
+    type: 'text',
+    editable: false,
+    cellHeaderClasses: 'width_percent_20',
+    headerCell: Backgrid.Extension.CustomHeaderCell,
+  },{
+    id: 'channel',
+    label: gettext('Event'),
+    cell: 'string',
+    type: 'text',
+    editable: false,
+    cellHeaderClasses: 'width_percent_20',
+    headerCell: Backgrid.Extension.CustomHeaderCell,
+  },{
+    id: 'pid',
+    label: gettext('Process ID'),
+    cell: 'string',
+    type: 'text',
+    editable: false,
+    cellHeaderClasses: 'width_percent_20',
+    headerCell: Backgrid.Extension.CustomHeaderCell,
+  },{
+    id: 'payload',
+    label: gettext('Payload'),
+    cell: 'string',
+    type: 'text',
+    editable: false,
+    cellHeaderClasses: 'width_percent_40',
+    headerCell: Backgrid.Extension.CustomHeaderCell,
+  }],
+});
+
+let NotificationCollection = Backbone.Collection.extend({
+  model: NotificationsModel,
+});
+
+let queryToolNotifications = {
+
+  collection: null,
+
+  /* This function is responsible to create and render the
+   * new backgrid for the notification tab.
+   */
+  renderNotificationsGrid: function(notifications_panel) {
+    if (!queryToolNotifications.collection)
+      queryToolNotifications.collection = new NotificationCollection();
+
+    let gridCols = [{
+      name: 'recorded_time',
+      label: gettext('Recorded time'),
+      type: 'text',
+      editable: false,
+      cell: 'string',
+    }, {
+      name: 'channel',
+      label: gettext('Event'),
+      type: 'text',
+      editable: false,
+      cell: 'string',
+    }, {
+      name: 'pid',
+      label: gettext('Process ID'),
+      type: 'text',
+      editable: false,
+      cell: 'string',
+    }, {
+      name: 'payload',
+      label: gettext('Payload'),
+      type: 'text',
+      editable: false,
+      cell: 'string',
+    }];
+
+    // Set up the grid
+    let notifications_grid = new Backgrid.Grid({
+      columns: gridCols,
+      collection: queryToolNotifications.collection,
+      className: 'backgrid table-bordered presentation table backgrid-striped',
+    });
+
+    // Render the grid
+    if (notifications_grid)
+      notifications_panel.$container.append(notifications_grid.render().el);
+  },
+
+  // This function is used to raise notify messages and update the
+  // notification grid.
+  updateNotifications: function(notify_messages) {
+    if (notify_messages != null && notify_messages.length > 0) {
+      for (let i in notify_messages) {
+        let notify_msg = '';
+        if (notify_messages[i].payload != '') {
+          notify_msg = gettext('Asynchronous notification "')
+            + notify_messages[i].channel
+            + gettext('" with payload "')
+            + notify_messages[i].payload
+            + gettext('" received from server process with PID ')
+            + notify_messages[i].pid;
+        }
+        else {
+          notify_msg = gettext('Asynchronous notification "')
+            + notify_messages[i].channel
+            + gettext('" received from server process with PID ')
+            + notify_messages[i].pid;
+        }
+
+        Alertify.info(notify_msg);
+      }
+
+      // Add notify messages to the collection.
+      queryToolNotifications.collection.add(notify_messages);
+    }
+  },
+};
+
+module.exports = queryToolNotifications;
diff --git a/web/pgadmin/static/js/sqleditor_utils.js b/web/pgadmin/static/js/sqleditor_utils.js
index d62a8e5..ffab047 100644
--- a/web/pgadmin/static/js/sqleditor_utils.js
+++ b/web/pgadmin/static/js/sqleditor_utils.js
@@ -72,6 +72,9 @@ define(['jquery', 'sources/gettext', 'sources/url_for'],
               $el.data('panel-visible') !== 'visible' ) {
           return;
         }
+
+        let sqleditor_obj = target;
+
         // Start polling..
         $.ajax({
           url: url,
@@ -82,6 +85,9 @@ define(['jquery', 'sources/gettext', 'sources/url_for'],
                 msg = res.data.message,
                 is_status_changed = false;
 
+              // Raise notify messages comes from database server.
+              sqleditor_obj.update_notifications(res.data.notifications);
+
               // Inject CSS as required
               switch(status) {
                   // Busy
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index c72505a..95d254b 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -543,10 +543,12 @@ def poll(trans_id):
     # There may be additional messages even if result is present
     # eg: Function can provide result as well as RAISE messages
     additional_messages = None
+    notifies = None
     if status == 'Success':
         messages = conn.messages()
         if messages:
             additional_messages = ''.join(messages)
+        notifies = conn.get_notifications()
 
     # Procedure/Function output may comes in the form of Notices from the
     # database server, so we need to append those outputs with the
@@ -564,6 +566,7 @@ def poll(trans_id):
             'rows_fetched_from': rows_fetched_from,
             'rows_fetched_to': rows_fetched_to,
             'additional_messages': additional_messages,
+            'notifications': notifies,
             'has_more_rows': has_more_rows,
             'colinfo': columns_info,
             'primary_keys': primary_keys,
@@ -1476,12 +1479,18 @@ def query_tool_status(trans_id):
 
     if conn and trans_obj and session_obj:
         status = conn.transaction_status()
+
+        # Check for the asynchronous notifications.
+        conn.check_notifications(True)
+        notifies = conn.get_notifications()
+
         return make_json_response(
             data={
                 'status': status,
                 'message': gettext(
-                    CONNECTION_STATUS_MESSAGE_MAPPING.get(status)
-                )
+                    CONNECTION_STATUS_MESSAGE_MAPPING.get(status),
+                ),
+                'notifications': notifies
             }
         )
     else:
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index f95389c..cab3d7d 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -20,6 +20,7 @@ define('tools.querytool', [
   'react', 'react-dom',
   'sources/keyboard_shortcuts',
   'sources/sqleditor/query_tool_actions',
+  'sources/sqleditor/query_tool_notifications',
   'pgadmin.datagrid',
   'sources/modify_animation',
   'sources/sqleditor/calculate_query_run_time',
@@ -36,8 +37,8 @@ define('tools.querytool', [
   pgExplain, GridSelector, ActiveCellCapture, clipboard, copyData, RangeSelectionHelper, handleQueryOutputKeyboardEvent,
   XCellSelectionModel, setStagedRows, SqlEditorUtils, ExecuteQuery, httpErrorHandler, FilterHandler,
   HistoryBundle, queryHistory, React, ReactDOM,
-  keyboardShortcuts, queryToolActions, Datagrid, modifyAnimation,
-  calculateQueryRunTime, callRenderAfterPoll) {
+  keyboardShortcuts, queryToolActions, queryToolNotifications, Datagrid,
+  modifyAnimation, calculateQueryRunTime, callRenderAfterPoll) {
   /* Return back, this has been called more than once */
   if (pgAdmin.SqlEditor)
     return pgAdmin.SqlEditor;
@@ -242,19 +243,32 @@ define('tools.querytool', [
         content: '<div id ="history_grid" class="sql-editor-history-container" tabindex: "0"></div>',
       });
 
+      var notifications = new pgAdmin.Browser.Panel({
+        name: 'notifications',
+        title: gettext('Notifications'),
+        width: '100%',
+        height: '100%',
+        isCloseable: false,
+        isPrivate: true,
+        content: '<div id ="notification_grid" class="sql-editor-notifications" tabindex: "0"></div>',
+      });
+
       // Load all the created panels
       data_output.load(main_docker);
       explain.load(main_docker);
       messages.load(main_docker);
       history.load(main_docker);
+      notifications.load(main_docker);
 
       // Add all the panels to the docker
       self.data_output_panel = main_docker.addPanel('data_output', wcDocker.DOCK.BOTTOM, sql_panel_obj);
       self.explain_panel = main_docker.addPanel('explain', wcDocker.DOCK.STACKED, self.data_output_panel);
       self.messages_panel = main_docker.addPanel('messages', wcDocker.DOCK.STACKED, self.data_output_panel);
       self.history_panel = main_docker.addPanel('history', wcDocker.DOCK.STACKED, self.data_output_panel);
+      self.notifications_panel = main_docker.addPanel('notifications', wcDocker.DOCK.STACKED, self.data_output_panel);
 
       self.render_history_grid();
+      queryToolNotifications.renderNotificationsGrid(self.notifications_panel);
 
       if (!self.handler.is_new_browser_tab) {
         // Listen on the panel closed event and notify user to save modifications.
@@ -3832,6 +3846,12 @@ define('tools.querytool', [
           }
         });
       },
+      /* This function is used to raise notify messages and update
+       * the notification grid.
+       */
+      update_notifications: function (notifications) {
+        queryToolNotifications.updateNotifications(notifications);
+      },
     });
 
   pgAdmin.SqlEditor = {
diff --git a/web/pgadmin/tools/sqleditor/utils/start_running_query.py b/web/pgadmin/tools/sqleditor/utils/start_running_query.py
index 8c598ff..8e9f4fb 100644
--- a/web/pgadmin/tools/sqleditor/utils/start_running_query.py
+++ b/web/pgadmin/tools/sqleditor/utils/start_running_query.py
@@ -47,6 +47,7 @@ class StartRunningQuery:
         transaction_object = pickle.loads(session_obj['command_obj'])
         can_edit = False
         can_filter = False
+        notifies = None
         if transaction_object is not None and session_obj is not None:
             # set fetched row count to 0 as we are executing query again.
             transaction_object.update_fetched_row_cnt(0)
@@ -88,6 +89,8 @@ class StartRunningQuery:
             can_edit = transaction_object.can_edit()
             can_filter = transaction_object.can_filter()
 
+            # Get the notifications
+            notifies = conn.get_notifications()
         else:
             status = False
             result = gettext(
@@ -97,7 +100,8 @@ class StartRunningQuery:
                 'status': status, 'result': result,
                 'can_edit': can_edit, 'can_filter': can_filter,
                 'info_notifier_timeout':
-                    self.blueprint_object.info_notifier_timeout.get()
+                    self.blueprint_object.info_notifier_timeout.get(),
+                'notifications': notifies
             }
         )
 
diff --git a/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py b/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py
index c839135..8332e7f 100644
--- a/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py
+++ b/web/pgadmin/tools/sqleditor/utils/tests/test_start_running_query.py
@@ -117,7 +117,8 @@ class StartRunningQueryTest(BaseTestGenerator):
                             'not found.',
                      can_edit=False,
                      can_filter=False,
-                     info_notifier_timeout=5
+                     info_notifier_timeout=5,
+                     notifications=None
                  )
              ),
              expect_internal_server_error_called_with=None,
@@ -276,7 +277,8 @@ class StartRunningQueryTest(BaseTestGenerator):
                      result='async function result output',
                      can_edit=True,
                      can_filter=True,
-                     info_notifier_timeout=5
+                     info_notifier_timeout=5,
+                     notifications=None
                  )
              ),
              expect_internal_server_error_called_with=None,
@@ -319,7 +321,8 @@ class StartRunningQueryTest(BaseTestGenerator):
                      result='async function result output',
                      can_edit=True,
                      can_filter=True,
-                     info_notifier_timeout=5
+                     info_notifier_timeout=5,
+                     notifications=None
                  )
              ),
              expect_internal_server_error_called_with=None,
@@ -362,7 +365,8 @@ class StartRunningQueryTest(BaseTestGenerator):
                      result='async function result output',
                      can_edit=True,
                      can_filter=True,
-                     info_notifier_timeout=5
+                     info_notifier_timeout=5,
+                     notifications=None
                  )
              ),
              expect_internal_server_error_called_with=None,
@@ -406,7 +410,8 @@ class StartRunningQueryTest(BaseTestGenerator):
                      result='async function result output',
                      can_edit=True,
                      can_filter=True,
-                     info_notifier_timeout=5
+                     info_notifier_timeout=5,
+                     notifications=None
                  )
              ),
              expect_internal_server_error_called_with=None,
@@ -511,8 +516,10 @@ class StartRunningQueryTest(BaseTestGenerator):
             connect=MagicMock(),
             execute_async=MagicMock(),
             execute_void=MagicMock(),
+            get_notifications=MagicMock(),
         )
         self.connection.connect.return_value = self.connection_connect_return
+        self.connection.get_notifications.return_value = None
         self.connection.execute_async.return_value = \
             self.execute_async_return_value
         if self.manager_connection_exception is None:
diff --git a/web/pgadmin/utils/driver/psycopg2/connection.py b/web/pgadmin/utils/driver/psycopg2/connection.py
index 315631c..23e45b0 100644
--- a/web/pgadmin/utils/driver/psycopg2/connection.py
+++ b/web/pgadmin/utils/driver/psycopg2/connection.py
@@ -16,6 +16,7 @@ object.
 import random
 import select
 import sys
+import datetime
 from collections import deque
 import simplejson as json
 import psycopg2
@@ -136,6 +137,13 @@ class Connection(BaseConnection):
         formatted error message if flag is set to true else return
         normal error message.
 
+    * check_notifications(required_polling)
+      - Check for the notify messages by polling the connection or after
+        execute is there in notifications.
+
+    * get_notifications()
+      - This function will returns list of notifications received from database
+        server.
     """
 
     def __init__(self, manager, conn_id, db, auto_reconnect=True, async=0,
@@ -155,6 +163,7 @@ class Connection(BaseConnection):
         self.execution_aborted = False
         self.row_count = 0
         self.__notices = None
+        self.__notifies = None
         self.password = None
         # This flag indicates the connection status (connected/disconnected).
         self.wasConnected = False
@@ -891,6 +900,7 @@ WHERE
 
         try:
             self.__notices = []
+            self.__notifies = []
             self.execution_aborted = False
             cur.execute(query, params)
             res = self._wait_timeout(cur.connection)
@@ -908,6 +918,9 @@ WHERE
                 )
             )
 
+            # Check for the asynchronous notifications.
+            self.check_notifications()
+
             if self.is_disconnected(pe):
                 raise ConnectionLost(
                     self.manager.sid,
@@ -1366,6 +1379,9 @@ Failed to reset the connection to the server due to following error:
             self.__notices.extend(self.conn.notices)
             self.conn.notices.clear()
 
+        # Check for the asynchronous notifications.
+        self.check_notifications()
+
         # We also need to fetch notices before we return from function in case
         # of any Exception, To avoid code duplication we will return after
         # fetching the notices in case of any Exception
@@ -1542,6 +1558,21 @@ Failed to reset the connection to the server due to following error:
         resp = []
         while self.__notices:
             resp.append(self.__notices.pop(0))
+
+        for notify in self.__notifies:
+            if notify.payload is not None and notify.payload is not '':
+                notify_msg = gettext(
+                    "Asynchronous notification \"{0}\" with payload \"{1}\" "
+                    "received from server process with PID {2}\n"
+                ).format(notify.channel, notify.payload, notify.pid)
+
+            else:
+                notify_msg = gettext(
+                    "Asynchronous notification \"{0}\" received from "
+                    "server process with PID {1}\n"
+                ).format(notify.channel, notify.pid)
+            resp.append(notify_msg)
+
         return resp
 
     def decode_to_utf8(self, value):
@@ -1711,3 +1742,34 @@ Failed to reset the connection to the server due to following error:
 
             return False
         return True
+
+    def check_notifications(self, required_polling=False):
+        """
+        Check for the notify messages by polling the connection or after
+        execute is there in notifications.
+        """
+        if self.conn and required_polling:
+            self.conn.poll()
+
+        if self.conn and hasattr(self.conn, 'notifies') and \
+                len(self.conn.notifies) > 0:
+            self.__notifies.extend(self.conn.notifies)
+            self.conn.notifies = []
+        else:
+            self.__notifies = []
+
+    def get_notifications(self):
+        """
+        This function will returns list of notifications received from database
+        server.
+        """
+        notifies = None
+        # Convert list of Notify objects into list of Dict.
+        if self.__notifies is not None and len(self.__notifies) > 0:
+            notifies = [{'recorded_time': str(datetime.datetime.now()),
+                         'channel': notify.channel,
+                         'payload': notify.payload,
+                         'pid': notify.pid
+                         } for notify in self.__notifies
+                        ]
+        return notifies
diff --git a/web/regression/javascript/sqleditor/execute_query_spec.js b/web/regression/javascript/sqleditor/execute_query_spec.js
index 06fefff..f1c4e9d 100644
--- a/web/regression/javascript/sqleditor/execute_query_spec.js
+++ b/web/regression/javascript/sqleditor/execute_query_spec.js
@@ -43,6 +43,7 @@ describe('ExecuteQuery', () => {
       'saveState',
       'initTransaction',
       'handle_connection_lost',
+      'update_notifications',
     ]);
     sqlEditorMock.transId = 123;
     sqlEditorMock.rows_affected = 1000;
@@ -76,7 +77,7 @@ describe('ExecuteQuery', () => {
         describe('when query was successful', () => {
           beforeEach(() => {
             response = {
-              data: {status: 'Success'},
+              data: {status: 'Success', notifications: [{'pid': 100}]},
             };
             networkMock.onGet('/sqleditor/query_tool/poll/123').reply(200, response);
 
@@ -97,7 +98,15 @@ describe('ExecuteQuery', () => {
           it('should render the results', (done) => {
             setTimeout(() => {
               expect(sqlEditorMock.call_render_after_poll)
-                .toHaveBeenCalledWith({status: 'Success'});
+                .toHaveBeenCalledWith({status: 'Success', notifications: [{'pid': 100}]});
+              done();
+            }, 0);
+          });
+
+          it('should update the notification panel', (done) => {
+            setTimeout(() => {
+              expect(sqlEditorMock.update_notifications)
+                .toHaveBeenCalledWith([{'pid': 100}]);
               done();
             }, 0);
           });
