diff --git a/docs/en_US/backup_dialog.rst b/docs/en_US/backup_dialog.rst
index df80a942a..ed9c43a65 100644
--- a/docs/en_US/backup_dialog.rst
+++ b/docs/en_US/backup_dialog.rst
@@ -203,21 +203,6 @@ command:
 
 * Click the *Cancel* button to exit without saving work.
 
-.. image:: images/backup_messages.png
-    :alt: Backup success notification popup
-    :align: center
-
-Use the **Stop Process** button to stop the Backup process.
-
-If the backup is successful, a popup window will confirm success. Click *More details* on the popup window to launch the *Process Watcher*. The *Process Watcher* logs all the activity associated with the backup and provides additional information for troubleshooting.
-
-.. image:: images/backup_process_watcher.png
-    :alt:  Backup process watcher
-    :align: center
-
-If the backup is unsuccessful, you can review the error messages returned by the
-backup command on the *Process Watcher*.
-
-.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the backup file on the client machine .
-
-.. |sm_icon| image:: images/sm_icon.png
+pgAdmin will run the backup process in background. You can view all the background
+process with there running status and logs on the :ref:`Processes <processes>`
+tab
\ No newline at end of file
diff --git a/docs/en_US/backup_globals_dialog.rst b/docs/en_US/backup_globals_dialog.rst
index 32c8310fc..0c2e9cc78 100644
--- a/docs/en_US/backup_globals_dialog.rst
+++ b/docs/en_US/backup_globals_dialog.rst
@@ -34,24 +34,6 @@ statements that should be included in the backup.
 Click the *Backup* button to build and execute a command based on your
 selections; click the *Cancel* button to exit without saving work.
 
-.. image:: images/backup_globals_messages.png
-    :alt: Backup globals success notification popup
-    :align: center
-
-Use the **Stop Process** button to stop the Backup process.
-
-If the backup is successful, a popup window will confirm success. Click *Click
-here for details* on the popup window to launch the *Process Watcher*. The
-*Process Watcher* logs all the activity associated with the backup and provides
-additional information for troubleshooting.
-
-.. image:: images/backup_globals_process_watcher.png
-    :alt:  Backup globals process watcher
-    :align: center
-
-If the backup is unsuccessful, review the error message returned by the
-*Process Watcher* to resolve any issue.
-
-.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the backup file on the client machine .
-
-.. |sm_icon| image:: images/sm_icon.png
+pgAdmin will run the backup process in background. You can view all the background
+process with there running status and logs on the :ref:`Processes <processes>`
+tab
\ No newline at end of file
diff --git a/docs/en_US/backup_server_dialog.rst b/docs/en_US/backup_server_dialog.rst
index cc5234aa2..7761d8886 100644
--- a/docs/en_US/backup_server_dialog.rst
+++ b/docs/en_US/backup_server_dialog.rst
@@ -122,24 +122,6 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg
 Click the *Backup* button to build and execute a command based on your
 selections; click the *Cancel* button to exit without saving work.
 
-.. image:: images/backup_server_messages.png
-    :alt: Backup server success notification popup
-    :align: center
-
-Use the **Stop Process** button to stop the Backup process.
-
-If the backup is successful, a popup window will confirm success. Click *Click
-here for details* on the popup window to launch the *Process Watcher*. The
-*Process Watcher* logs all the activity associated with the backup and provides
-additional information for troubleshooting.
-
-.. image:: images/backup_server_process_watcher.png
-    :alt:  Backup server process watcher
-    :align: center
-
-If the backup is unsuccessful, review the error message returned by the
-*Process Watcher* to resolve any issue.
-
-.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the backup file on the client machine .
-
-.. |sm_icon| image:: images/sm_icon.png
+pgAdmin will run the backup process in background. You can view all the background
+process with there running status and logs on the :ref:`Processes <processes>`
+tab
\ No newline at end of file
diff --git a/docs/en_US/cloud_aws_rds.rst b/docs/en_US/cloud_aws_rds.rst
index 3c32022ef..3f00c7159 100644
--- a/docs/en_US/cloud_aws_rds.rst
+++ b/docs/en_US/cloud_aws_rds.rst
@@ -89,5 +89,8 @@ button to deploy the instance on Amazon RDS.
 
 Once you click on the finish, one background process will start which will
 deploy the instance in the cloud and monitor the progress of the deployment.
+You can view all the background process with there running status and logs
+on the :ref:`Processes <processes>` tab
+
 The Server will be added to the tree with the cloud deployment icon. Once the
 deployment is done, the server details will be updated.
diff --git a/docs/en_US/cloud_azure_postgresql.rst b/docs/en_US/cloud_azure_postgresql.rst
index f90594308..ed734e667 100644
--- a/docs/en_US/cloud_azure_postgresql.rst
+++ b/docs/en_US/cloud_azure_postgresql.rst
@@ -107,6 +107,8 @@ button to deploy the instance on Azure PostgreSQL.
 
 Once you click on the finish, one background process will start which will
 deploy the instance in the cloud and monitor the progress of the deployment.
+You can view all the background process with there running status and logs
+on the :ref:`Processes <processes>` tab
 
 .. image:: images/cloud_azure_bg_process_watcher.png
     :alt: Cloud Deployment
diff --git a/docs/en_US/cloud_edb_biganimal.rst b/docs/en_US/cloud_edb_biganimal.rst
index 7103d4e61..ac79e57a1 100644
--- a/docs/en_US/cloud_edb_biganimal.rst
+++ b/docs/en_US/cloud_edb_biganimal.rst
@@ -87,5 +87,8 @@ button to deploy the instance on EDB BigAnimal.
 
 Once you click on the finish, one background process will start which will
 deploy the instance in the cloud and monitor the progress of the deployment.
+You can view all the background process with there running status and logs
+on the :ref:`Processes <processes>` tab
+
 The Server will be added to the tree with the cloud deployment icon. Once the
 deployment is done, the server details will be updated.
diff --git a/docs/en_US/images/backup_globals_messages.png b/docs/en_US/images/backup_globals_messages.png
deleted file mode 100644
index c56440e61f4e4053d4d1359ca52ebde6dfad48c5..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/backup_globals_process_watcher.png b/docs/en_US/images/backup_globals_process_watcher.png
deleted file mode 100644
index a5617a0ae35d7b1857f33eada85cc307de8baf87..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/backup_messages.png b/docs/en_US/images/backup_messages.png
deleted file mode 100644
index db85032f13ef0725418c0b9681291969f2ba34bd..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/backup_server_messages.png b/docs/en_US/images/backup_server_messages.png
deleted file mode 100644
index 0c8dcc6c2f5c833d731d32ab4335e44ae0f989d5..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/backup_server_process_watcher.png b/docs/en_US/images/backup_server_process_watcher.png
deleted file mode 100644
index 725a0062ef7d745b92f1a85390d6cfa0004d454b..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/maintenance_complete.png b/docs/en_US/images/maintenance_complete.png
deleted file mode 100644
index df32ee1eb5fd835771272db7bcaded4573f31198..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/maintenance_pw.png b/docs/en_US/images/maintenance_pw.png
deleted file mode 100644
index e487409548421ca7b8c9e44b93be5e2c950a8dba..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/processes_details.png b/docs/en_US/images/processes_details.png
new file mode 100644
index 0000000000000000000000000000000000000000..48ffc73e932ac8cd547f2cdb887609259e3e675b
GIT binary patch
diff --git a/docs/en_US/images/processes_main.png b/docs/en_US/images/processes_main.png
new file mode 100644
index 0000000000000000000000000000000000000000..bd59285a98f25535c6574ddd4227bad099db27ec
GIT binary patch
diff --git a/docs/en_US/images/restore_messages.png b/docs/en_US/images/restore_messages.png
deleted file mode 100644
index fc98133756607398c58b01b502894e2ff2726795..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/restore_process_watcher.png b/docs/en_US/images/restore_process_watcher.png
deleted file mode 100644
index 95358cf591675c82199e844bacdcfbb7eddd5a47..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/docs/en_US/images/sm_icon.png b/docs/en_US/images/sm_icon.png
index 13522104e7abefcb0da49be64bfac05dbe296721..9640d9dc6b129690258cb9bd8566920db4f9e6b5 100644
GIT binary patch
diff --git a/docs/en_US/index.rst b/docs/en_US/index.rst
index c43ab5b85..0bc680f0d 100644
--- a/docs/en_US/index.rst
+++ b/docs/en_US/index.rst
@@ -23,6 +23,7 @@ of database objects.
    management_basics
    backup_and_restore
    developer_tools
+   processes
    pgagent
    contributions
    release_notes
diff --git a/docs/en_US/maintenance_dialog.rst b/docs/en_US/maintenance_dialog.rst
index 1f7ddc2b4..de446d128 100644
--- a/docs/en_US/maintenance_dialog.rst
+++ b/docs/en_US/maintenance_dialog.rst
@@ -45,18 +45,6 @@ switch to the *No* position; by default, status messages are included.
 When you've completed the dialog, click *OK* to start the background process;
 to exit the dialog without performing maintenance operations, click *Cancel*.
 
-pgAdmin will inform you when the background process completes:
-
-.. image:: images/maintenance_complete.png
-    :alt: Maintenance completion notification
-    :align: center
-
-Use the **Stop Process** button to stop the Maintenance process.
-
-Use the *Click here for details* link on the notification to open the *Process
-Watcher* and review detailed information about the execution of the command that
-performed the import or export:
-
-.. image:: images/maintenance_pw.png
-    :alt: Maintenance process watcher
-    :align: center
+pgAdmin will run the maintenance process in background. You can view all the background
+process with there running status and logs on the :ref:`Processes <processes>`
+tab
\ No newline at end of file
diff --git a/docs/en_US/processes.rst b/docs/en_US/processes.rst
new file mode 100644
index 000000000..e10e74e02
--- /dev/null
+++ b/docs/en_US/processes.rst
@@ -0,0 +1,46 @@
+.. _processes:
+
+***********************
+`Processes`:index:
+***********************
+
+There are certain tasks which pgAdmin runs in the background. The processes
+running in the background can be viewed in the processes tab. It shows the
+process details of Backup, Restore, Maintenance, Import/Export and Cloud instance
+creation.
+
+.. image:: images/processes_main.png
+    :alt: Processes Tab
+    :align: center
+
+The columns of the processes table shows:
+
+* The *PID* of the forked OS process.
+* The *Description* of the task.
+* The *Start Time* of the process.
+* The current *Status* of the process. It can be Running, Finished, Failed, Terminated.
+* The *Time Taken* to complete. It will keep updating if it is running.
+
+There are three action buttons on each row:
+
+* The *Stop Process* button allows you to kill a running process.
+* The *Delete and Acknowledge* button allows you to clear the process info and logs.
+* The *More details* button allows you to open the process watcher which shows the
+  process logs and other details.
+
+
+Process Watcher
+*********************
+
+.. image:: images/processes_details.png
+    :alt: Process Watcher
+    :align: center
+
+
+The Process Watcher logs all the activity associated with the process/task and provides
+additional information for troubleshooting
+Use the **Stop Process** button to stop the Backup process.
+
+.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the backup file on the client machine .
+
+.. |sm_icon| image:: images/sm_icon.png
\ No newline at end of file
diff --git a/docs/en_US/restore_dialog.rst b/docs/en_US/restore_dialog.rst
index 02468a082..c2f72c23e 100644
--- a/docs/en_US/restore_dialog.rst
+++ b/docs/en_US/restore_dialog.rst
@@ -143,17 +143,6 @@ command, click the *Restore* button to start the process, or click the *Cancel*
 button to exit without saving your work. A popup will confirm if the restore is
 successful.
 
-.. image:: images/restore_messages.png
-    :alt: Restore dialog notifications
-    :align: center
-
-Use the **Stop Process** button to stop the Restore process.
-
-Click *Click here for details* on the popup to launch the *Process Watcher*. The
-*Process Watcher* logs all the activity associated with the restore, and
-provides additional information for troubleshooting should the restore command
-encounter problems.
-
-.. image:: images/restore_process_watcher.png
-    :alt: Restore dialog process watcher
-    :align: center
+pgAdmin will run the restore process in background. You can view all the background
+process with there running status and logs on the :ref:`Processes <processes>`
+tab
\ No newline at end of file
diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py
index 169f506ba..4f7d376cf 100644
--- a/web/pgadmin/browser/register_browser_preferences.py
+++ b/web/pgadmin/browser/register_browser_preferences.py
@@ -130,6 +130,12 @@ def register_browser_preferences(self):
         )
     )
 
+    self.table_row_count_threshold = self.preference.register(
+        'processes', 'process_retain_days',
+        gettext("Process details/logs retain days"), 'integer', 5,
+        category_label=gettext('Processes')
+    )
+
     fields = [
         {'name': 'key', 'type': 'keyCode', 'label': gettext('Key')},
         {'name': 'shift', 'type': 'checkbox', 'label': gettext('Shift')},
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py
index 210feab16..f9183d997 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py
@@ -174,7 +174,7 @@ class Message(IProcessDesc):
         return gettext("Refresh Materialized View")
 
     def details(self, cmd, args):
-        res = gettext("Refresh Materialized View ({0})")
+        msg = gettext("Refresh Materialized View ({0})")
         opts = []
         if not self.data['is_with_data']:
             opts.append(gettext("WITH NO DATA"))
@@ -184,17 +184,12 @@ class Message(IProcessDesc):
         if self.data['is_concurrent']:
             opts.append(gettext("CONCURRENTLY"))
 
-        res = res.format(', '.join(str(x) for x in opts))
+        msg = msg.format(', '.join(str(x) for x in opts))
 
-        res = '<div>' + html.safe_str(res)
-
-        res += '</div><div class="py-1">'
-        res += gettext("Running Query:")
-        res += '<div class="pg-bg-cmd enable-selection p-1">'
-        res += html.safe_str(self.query)
-        res += '</div></div>'
-
-        return res
+        return {
+            "message": msg,
+            "query": self.query
+        }
 
 
 class MViewModule(ViewModule):
@@ -2276,6 +2271,7 @@ class MViewNode(ViewNode, VacuumSettings):
             return make_json_response(
                 data={
                     'job_id': jid,
+                    'desc': p.desc.message,
                     'status': True,
                     'info': gettext(
                         'Materialized view refresh job created.')
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
index b9a86008d..d91e37ea4 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
@@ -205,7 +205,7 @@ define('pgadmin.node.mview', [
               if (refreshed_res.data && refreshed_res.data.status) {
               //Do nothing as we are creating the job and exiting from the main dialog
                 Notify.success(refreshed_res.data.info);
-                pgBrowser.Events.trigger('pgadmin-bgprocess:created');
+                pgBrowser.BgProcessManager.startProcess(refreshed_res.data.job_id, refreshed_res.data.desc);
               } else {
                 Notify.alert(
                   gettext('Failed to create materialized view refresh job.'),
diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index 53d58c253..3fa870332 100644
--- a/web/pgadmin/browser/static/js/browser.js
+++ b/web/pgadmin/browser/static/js/browser.js
@@ -266,6 +266,19 @@ define('pgadmin.browser', [
         content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependents-container d-none"></div></div>',
         events: panelEvents,
       }),
+      // Background processes
+      'processes': new pgAdmin.Browser.Panel({
+        name: 'processes',
+        title: gettext('Processes'),
+        icon: '',
+        width: 500,
+        isCloseable: true,
+        isPrivate: false,
+        limit: 1,
+        canHide: true,
+        content: '<div class="negative-space p-2"><div class="pg-panel-processes-container d-none"></div></div>',
+        events: panelEvents,
+      }),
     },
     // We also support showing dashboards, HTML file, external URL
     frames: {},
diff --git a/web/pgadmin/browser/static/js/layout.js b/web/pgadmin/browser/static/js/layout.js
index 689028f3d..fff14e7ba 100644
--- a/web/pgadmin/browser/static/js/layout.js
+++ b/web/pgadmin/browser/static/js/layout.js
@@ -42,6 +42,8 @@ _.extend(pgBrowser, {
       'dependencies', wcDocker.DOCK.STACKED, dashboardPanel);
     docker.addPanel(
       'dependents', wcDocker.DOCK.STACKED, dashboardPanel);
+    docker.addPanel(
+      'processes', wcDocker.DOCK.STACKED, dashboardPanel);
   },
 
   save_current_layout: function(layout_id, docker) {
diff --git a/web/pgadmin/browser/static/js/panel.js b/web/pgadmin/browser/static/js/panel.js
index 8f1d1b7ab..a2cd057ba 100644
--- a/web/pgadmin/browser/static/js/panel.js
+++ b/web/pgadmin/browser/static/js/panel.js
@@ -122,7 +122,7 @@ define(
                 that.resizedContainer.apply(myPanel);
               }
 
-              if (myPanel._type == 'dashboard') {
+              if (myPanel._type == 'dashboard' || myPanel._type == 'processes') {
                 getPanelView(
                   pgBrowser.tree,
                   $container[0],
diff --git a/web/pgadmin/browser/static/js/panel_view.jsx b/web/pgadmin/browser/static/js/panel_view.jsx
index 8302af60a..c1274b840 100644
--- a/web/pgadmin/browser/static/js/panel_view.jsx
+++ b/web/pgadmin/browser/static/js/panel_view.jsx
@@ -17,6 +17,7 @@ import SQL from '../../../misc/sql/static/js/SQL';
 import Dashboard from '../../../dashboard/static/js/Dashboard';
 import _ from 'lodash';
 import { CollectionNodeView } from '../../../misc/properties/CollectionNodeProperties';
+import Processes from '../../../misc/bgprocess/static/js/Processes';
 
 
 /* The entry point for rendering React based view in properties, called in node.js */
@@ -131,6 +132,14 @@ export function getPanelView(
       container
     );
   }
+  if (panelType == 'processes') {
+    ReactDOM.render(
+      <Theme>
+        <Processes />
+      </Theme>,
+      container
+    );
+  }
 }
 
 /* When switching from normal node to collection node, clean up the React mounted DOM */
diff --git a/web/pgadmin/dashboard/static/js/Dashboard.jsx b/web/pgadmin/dashboard/static/js/Dashboard.jsx
index 31f6cd0e0..c8f5b0f04 100644
--- a/web/pgadmin/dashboard/static/js/Dashboard.jsx
+++ b/web/pgadmin/dashboard/static/js/Dashboard.jsx
@@ -143,7 +143,7 @@ export default function Dashboard({
     {
       accessor: 'name',
       Header: gettext('Name'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 50,
@@ -153,7 +153,7 @@ export default function Dashboard({
     {
       accessor: 'category',
       Header: gettext('Category'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 50,
@@ -161,7 +161,7 @@ export default function Dashboard({
     {
       accessor: 'setting',
       Header: gettext('Value'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 50,
@@ -170,7 +170,7 @@ export default function Dashboard({
     {
       accessor: 'unit',
       Header: gettext('Unit'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -179,7 +179,7 @@ export default function Dashboard({
     {
       accessor: 'short_desc',
       Header: gettext('Description'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
@@ -189,7 +189,7 @@ export default function Dashboard({
     {
       accessor: 'terminate_query',
       Header: () => null,
-      sortble: true,
+      sortable: true,
       resizable: false,
       disableGlobalFilter: false,
       width: 35,
@@ -261,7 +261,7 @@ export default function Dashboard({
     {
       accessor: 'cancel_Query',
       Header: () => null,
-      sortble: true,
+      sortable: true,
       resizable: false,
       disableGlobalFilter: false,
       width: 35,
@@ -330,7 +330,7 @@ export default function Dashboard({
     {
       accessor: 'view_active_query',
       Header: () => null,
-      sortble: true,
+      sortable: true,
       resizable: false,
       disableGlobalFilter: false,
       width: 35,
@@ -374,7 +374,7 @@ export default function Dashboard({
     {
       accessor: 'pid',
       Header: gettext('PID'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -383,7 +383,7 @@ export default function Dashboard({
     {
       accessor: 'datname',
       Header: gettext('Database'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -393,7 +393,7 @@ export default function Dashboard({
     {
       accessor: 'usename',
       Header: gettext('User'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -402,7 +402,7 @@ export default function Dashboard({
     {
       accessor: 'application_name',
       Header: gettext('Application'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -410,7 +410,7 @@ export default function Dashboard({
     {
       accessor: 'client_addr',
       Header: gettext('Client'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -418,7 +418,7 @@ export default function Dashboard({
     {
       accessor: 'backend_start',
       Header: gettext('Backend start'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 100,
@@ -426,7 +426,7 @@ export default function Dashboard({
     {
       accessor: 'xact_start',
       Header: gettext('Transaction start'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -434,7 +434,7 @@ export default function Dashboard({
     {
       accessor: 'state',
       Header: gettext('State'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -444,7 +444,7 @@ export default function Dashboard({
     {
       accessor: 'waiting',
       Header: gettext('Waiting'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       isVisible: treeNodeInfo?.server?.version < 90600
@@ -452,14 +452,14 @@ export default function Dashboard({
     {
       accessor: 'wait_event',
       Header: gettext('Wait event'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       accessor: 'blocking_pids',
       Header: gettext('Blocking PIDs'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
@@ -469,7 +469,7 @@ export default function Dashboard({
     {
       accessor: 'pid',
       Header: gettext('PID'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -478,7 +478,7 @@ export default function Dashboard({
     {
       accessor: 'datname',
       Header: gettext('Database'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -488,7 +488,7 @@ export default function Dashboard({
     {
       accessor: 'locktype',
       Header: gettext('Lock type'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -497,14 +497,14 @@ export default function Dashboard({
     {
       accessor: 'relation',
       Header: gettext('Target relation'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       accessor: 'page',
       Header: gettext('Page'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -513,7 +513,7 @@ export default function Dashboard({
     {
       accessor: 'tuple',
       Header: gettext('Tuple'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -521,7 +521,7 @@ export default function Dashboard({
     {
       accessor: 'virtualxid',
       Header: gettext('vXID (target)'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 50,
@@ -530,7 +530,7 @@ export default function Dashboard({
     {
       accessor: 'transactionid',
       Header: gettext('XID (target)'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 50,
@@ -539,7 +539,7 @@ export default function Dashboard({
     {
       accessor: 'classid',
       Header: gettext('Class'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -548,7 +548,7 @@ export default function Dashboard({
     {
       accessor: 'objid',
       Header: gettext('Object ID'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 50,
@@ -558,7 +558,7 @@ export default function Dashboard({
     {
       accessor: 'virtualtransaction',
       Header: gettext('vXID (owner)'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 50,
@@ -566,7 +566,7 @@ export default function Dashboard({
     {
       accessor: 'mode',
       Header: gettext('Mode'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
@@ -574,7 +574,7 @@ export default function Dashboard({
       id: 'granted',
       accessor: 'granted',
       Header: gettext('Granted?'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 30,
@@ -587,14 +587,14 @@ export default function Dashboard({
     {
       accessor: 'git',
       Header: gettext('Name'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       accessor: 'datname',
       Header: gettext('Database'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 26,
@@ -604,21 +604,21 @@ export default function Dashboard({
     {
       accessor: 'Owner',
       Header: gettext('Owner'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       accessor: 'transaction',
       Header: gettext('XID'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       accessor: 'prepared',
       Header: gettext('Prepared at'),
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
diff --git a/web/pgadmin/misc/bgprocess/processes.py b/web/pgadmin/misc/bgprocess/processes.py
index 2510cc29d..abaad3fd4 100644
--- a/web/pgadmin/misc/bgprocess/processes.py
+++ b/web/pgadmin/misc/bgprocess/processes.py
@@ -16,17 +16,19 @@ import os
 import sys
 import psutil
 from abc import ABCMeta, abstractproperty, abstractmethod
-from datetime import datetime
+from datetime import datetime, timedelta
 from pickle import dumps, loads
 from subprocess import Popen, PIPE
 import logging
 import json
+import shutil
 
 from pgadmin.utils import u_encode, file_quote, fs_encoding, \
     get_complete_file_path, get_storage_directory, IS_WIN
 from pgadmin.browser.server_groups.servers.utils import does_server_exists
 from pgadmin.utils.constants import KERBEROS
 from pgadmin.utils.locker import ConnectionLocker
+from pgadmin.utils.preferences import Preferences
 
 import pytz
 from dateutil import parser
@@ -463,8 +465,9 @@ class BatchProcess(object):
         idx = 0
         c = re.compile(r"(\d+),(.*$)")
 
+        # If file is not present then
         if not os.path.isfile(logfile):
-            return 0, False
+            return 0, True
 
         with open(logfile, 'rb') as f:
             eofs = os.fstat(f.fileno()).st_size
@@ -695,8 +698,22 @@ class BatchProcess(object):
         processes = Process.query.filter_by(user_id=current_user.id)
         changed = False
 
+        browser_preference = Preferences.module('browser')
+        expiry_add = timedelta(
+            browser_preference.preference('process_retain_days').get() or 1
+        )
+
         res = []
-        for p in processes:
+        for p in [*processes]:
+            if p.start_time is not None:
+                process_expiration_time = \
+                    parser.parse(p.start_time) + expiry_add
+                if datetime.now(process_expiration_time.tzinfo) >= \
+                        process_expiration_time:
+                    shutil.rmtree(p.logdir, True)
+                    db.session.delete(p)
+                    changed = True
+
             status, updated = BatchProcess.update_process_info(p)
             if not status:
                 continue
@@ -732,6 +749,7 @@ class BatchProcess(object):
                 'acknowledge': p.acknowledge,
                 'execution_time': execution_time,
                 'process_state': p.process_state,
+                'utility_pid': p.utility_pid,
                 'current_storage_dir': current_storage_dir,
             })
 
@@ -834,13 +852,15 @@ class BatchProcess(object):
             process.terminate()
             # Update the process state to "Terminated"
             p.process_state = PROCESS_TERMINATED
-            db.session.commit()
+        except psutil.NoSuchProcess:
+            p.process_state = PROCESS_TERMINATED
         except psutil.Error as e:
             current_app.logger.warning(
                 _("Unable to kill the background process '{0}'").format(
                     p.utility_pid)
             )
             current_app.logger.exception(e)
+        db.session.commit()
 
     @staticmethod
     def update_server_id(_pid, _sid):
diff --git a/web/pgadmin/misc/bgprocess/static/css/bgprocess.css b/web/pgadmin/misc/bgprocess/static/css/bgprocess.css
deleted file mode 100644
index c5f431a35..000000000
--- a/web/pgadmin/misc/bgprocess/static/css/bgprocess.css
+++ /dev/null
@@ -1,59 +0,0 @@
-
-.ajs-bg-bgprocess .col-xs-12 {
-  padding-right: 5px;
-  padding-left: 5px;
-}
-
-.ajs-bg-bgprocess > .pg-bg-bgprocess > .pg-bg-status {
-  padding: 2px;
-  margin: 0px 5px;
-  text-align: center;
-  border-radius: 2px;
-  -moz-border-radius: 2px;
-  -webkit-border-radius: 2px;
-}
-
-.pg-bg-process-logs {
-  width: 100%;
-  -webkit-user-select: text;
-  -moz-user-select: text;
-  -ms-user-select: text;
-  user-select: text;
-}
-
-ol.pg-bg-process-logs {
-  height: 100%;
-  overflow: auto;
-  width: 100%;
-}
-
-.pg-panel-content .bg-process-stats p{
-  display: inline;
-  padding-left: 5px;
-  margin-bottom: 0;
-  font-size: 13px;
-}
-
-.pg-panel-content .bg-process-footer p {
-  display: inline;
-  padding-left: 5px;
-  font-size: 13px;
-}
-
-.bg-process-footer .bg-process-status {
-  padding-left: 0;
-}
-
-.bg-process-footer .bg-process-exec-time {
-  padding-right: 0;
-}
-
-.pg-bg-bgprocess .ajs-commands {
-  right: -13px;
-  top: 2px;
-  opacity: 0.5;
-}
-
-.pg-bg-bgprocess:hover .bg-close {
-  opacity: 0.95;
-}
diff --git a/web/pgadmin/misc/bgprocess/static/js/BgProcessManager.js b/web/pgadmin/misc/bgprocess/static/js/BgProcessManager.js
new file mode 100644
index 000000000..88a810b40
--- /dev/null
+++ b/web/pgadmin/misc/bgprocess/static/js/BgProcessManager.js
@@ -0,0 +1,191 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import getApiInstance, { parseApiError } from '../../../../static/js/api_instance';
+import url_for from 'sources/url_for';
+import Notifier from '../../../../static/js/helpers/Notifier';
+import EventBus from '../../../../static/js/helpers/EventBus';
+import * as BgProcessNotify from './BgProcessNotify';
+import showDetails from './showDetails';
+
+const WORKER_INTERVAL = 1000;
+
+export const BgProcessManagerEvents = {
+  LIST_UPDATED: 'LIST_UPDATED',
+};
+
+export const BgProcessManagerProcessState = {
+  PROCESS_NOT_STARTED: 0,
+  PROCESS_STARTED: 1,
+  PROCESS_FINISHED: 2,
+  PROCESS_TERMINATED: 3,
+  /* Supported by front end only */
+  PROCESS_TERMINATING: 10,
+  PROCESS_FAILED: 11,
+};
+
+
+export default class BgProcessManager {
+  static instance;
+
+  static getInstance(...args) {
+    if (!BgProcessManager.instance) {
+      BgProcessManager.instance = new BgProcessManager(...args);
+    }
+    return BgProcessManager.instance;
+  }
+
+  constructor(pgBrowser) {
+    this.api = getApiInstance();
+    this.pgBrowser = pgBrowser;
+    this._procList = [];
+    this._workerId = null;
+    this._pendingJobId = [];
+    this._eventManager = new EventBus();
+  }
+
+  init() {
+    if (this.initialized) {
+      return;
+    }
+    this.initialized = true;
+    this.startWorker();
+  }
+
+  get procList() {
+    return this._procList;
+  }
+
+  set procList(val) {
+    throw new Error('Property processList is readonly.', val);
+  }
+
+  startWorker() {
+    let self = this;
+    self.syncProcesses();
+    this._workerId = setInterval(()=>{
+      if(self._pendingJobId.length > 0) {
+        self.syncProcesses();
+      }
+    }, WORKER_INTERVAL);
+  }
+
+  evaluateProcessState(p) {
+    let retState = p.process_state;
+    if((p.etime || p.exit_code !=null) && p.process_state == BgProcessManagerProcessState.PROCESS_STARTED) {
+      retState =  BgProcessManagerProcessState.PROCESS_FINISHED;
+    }
+    if(retState == BgProcessManagerProcessState.PROCESS_FINISHED && p.exit_code != 0) {
+      retState = BgProcessManagerProcessState.PROCESS_FAILED;
+    }
+    return retState;
+  }
+
+  syncProcesses() {
+    this.api.get(url_for('bgprocess.list'))
+      .then((res)=>{
+        this._procList = res.data?.map((p)=>{
+          return {
+            ...p,
+            process_state: this.evaluateProcessState(p),
+          };
+        });
+        this._eventManager.fireEvent(BgProcessManagerEvents.LIST_UPDATED);
+        this.checkPending();
+      })
+      .catch((err)=>{
+        console.error(err);
+      });
+  }
+
+  checkPending() {
+    const completedProcIds = this.procList.filter((p)=>{
+      if(![
+        BgProcessManagerProcessState.PROCESS_NOT_STARTED,
+        BgProcessManagerProcessState.PROCESS_STARTED,
+        BgProcessManagerProcessState.PROCESS_TERMINATING].includes(p.process_state)) {
+        return true;
+      }
+    }).map((p)=>p.id);
+    this._pendingJobId = this._pendingJobId.filter((id)=>{
+      if(completedProcIds.includes(id)) {
+        let p = this.procList.find((p)=>p.id==id);
+        BgProcessNotify.processCompleted(p?.desc, p?.process_state, this.openProcessesPanel.bind(this));
+        return false;
+      }
+      return true;
+    });
+  }
+
+  startProcess(jobId, desc) {
+    if(jobId) {
+      this._pendingJobId.push(jobId);
+      BgProcessNotify.processStarted(desc, this.openProcessesPanel.bind(this));
+    }
+  }
+
+  stopProcess(jobId) {
+    this.procList.find((p)=>p.id == jobId).process_state = BgProcessManagerProcessState.PROCESS_TERMINATING;
+    this._eventManager.fireEvent(BgProcessManagerEvents.LIST_UPDATED);
+    this.api.put(url_for('bgprocess.stop_process', {
+      pid: jobId,
+    }))
+      .then(()=>{
+        this.procList.find((p)=>p.id == jobId).process_state = BgProcessManagerProcessState.PROCESS_TERMINATED;
+        this._eventManager.fireEvent(BgProcessManagerEvents.LIST_UPDATED);
+      })
+      .catch((err)=>{
+        Notifier.error(parseApiError(err));
+      });
+  }
+
+  acknowledge(jobId) {
+    const removeJob = ()=>{
+      this._procList = this.procList.filter((p)=>p.id!=jobId);
+      this._eventManager.fireEvent(BgProcessManagerEvents.LIST_UPDATED);
+    };
+    this.api.put(url_for('bgprocess.acknowledge', {
+      pid: jobId,
+    }))
+      .then(()=>{
+        removeJob();
+      })
+      .catch((err)=>{
+        if(err.response?.status == 410) {
+        /* Object not available */
+          removeJob();
+        } else {
+          Notifier.error(parseApiError(err));
+        }
+      });
+  }
+
+  viewJobDetails(jobId) {
+    showDetails(this.procList.find((p)=>p.id==jobId));
+  }
+
+  openProcessesPanel() {
+    let processPanel = this.pgBrowser.docker.findPanels('processes');
+    if(processPanel.length > 0) {
+      processPanel = processPanel[0];
+    } else {
+      let propertiesPanel = this.pgBrowser.docker.findPanels('properties');
+      processPanel = this.pgBrowser.docker.addPanel('processes', window.wcDocker.DOCK.STACKED, propertiesPanel[0]);
+    }
+    processPanel.focus();
+  }
+
+  registerListener(event, callback) {
+    this._eventManager.registerListener(event, callback);
+  }
+
+  deregisterListener(event, callback) {
+    this._eventManager.deregisterListener(event, callback);
+  }
+}
diff --git a/web/pgadmin/misc/bgprocess/static/js/BgProcessNotify.jsx b/web/pgadmin/misc/bgprocess/static/js/BgProcessNotify.jsx
new file mode 100644
index 000000000..1efb14119
--- /dev/null
+++ b/web/pgadmin/misc/bgprocess/static/js/BgProcessNotify.jsx
@@ -0,0 +1,97 @@
+import { Box, makeStyles } from '@material-ui/core';
+import React from 'react';
+import Notifier from '../../../../static/js/helpers/Notifier';
+import CloseIcon from '@material-ui/icons/CloseRounded';
+import { DefaultButton, PgIconButton } from '../../../../static/js/components/Buttons';
+import clsx from 'clsx';
+import DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined';
+import { BgProcessManagerProcessState } from './BgProcessManager';
+import PropTypes from 'prop-types';
+import gettext from 'sources/gettext';
+
+
+const useStyles = makeStyles((theme)=>({
+  container: {
+    borderRadius: theme.shape.borderRadius,
+    padding: '0.25rem 1rem 1rem',
+    minWidth: '325px',
+    ...theme.mixins.panelBorder.all,
+  },
+  containerHeader: {
+    height: '32px',
+    display: 'flex',
+    justifyContent: 'space-between',
+    fontWeight: 'bold',
+    alignItems: 'center',
+    borderTopLeftRadius: 'inherit',
+    borderTopRightRadius: 'inherit',
+  },
+  containerBody: {
+    marginTop: '1rem',
+  },
+  containerSuccess: {
+    borderColor: theme.palette.success.main,
+    backgroundColor: theme.palette.success.light,
+  },
+  iconSuccess: {
+    color: theme.palette.success.main,
+  },
+  containerError: {
+    borderColor: theme.palette.error.main,
+    backgroundColor: theme.palette.error.light,
+  },
+  iconError: {
+    color: theme.palette.error.main,
+  },
+}));
+
+function ProcessNotifyMessage({title, desc, onClose, onViewProcess, success=true}) {
+  const classes = useStyles();
+  return (
+    <Box className={clsx(classes.container, (success ? classes.containerSuccess : classes.containerError))}>
+      <Box display="flex" justifyContent="space-between" className={classes.containerHeader}>
+        <Box marginRight={'1rem'}>{title}</Box>
+        <PgIconButton size="xs" noBorder icon={<CloseIcon />} onClick={onClose} title={'Close'} className={success ? classes.iconSuccess : classes.iconError} />
+      </Box>
+      <Box className={classes.containerBody}>
+        <Box>{desc}</Box>
+        <Box marginTop={'1rem'} display="flex">
+          <DefaultButton startIcon={<DescriptionOutlinedIcon />} onClick={onViewProcess}>View Processes</DefaultButton>
+        </Box>
+      </Box>
+    </Box>
+  );
+}
+ProcessNotifyMessage.propTypes = {
+  title: PropTypes.string.isRequired,
+  desc: PropTypes.string.isRequired,
+  onClose: PropTypes.func,
+  onViewProcess: PropTypes.func,
+  success: PropTypes.bool,
+};
+
+
+export function processStarted(desc, onViewProcess) {
+  Notifier.notify(
+    <ProcessNotifyMessage title={gettext('Process started')} desc={desc} onViewProcess={onViewProcess}/>,
+    null
+  );
+}
+
+export function processCompleted(desc, process_state, onViewProcess) {
+  let title = gettext('Process completed');
+  let success = true;
+  if(process_state == BgProcessManagerProcessState.PROCESS_TERMINATED) {
+    title = gettext('Process terminated');
+    success = false;
+  } else if(process_state == BgProcessManagerProcessState.PROCESS_FAILED) {
+    title = gettext('Process failed');
+    success = false;
+  }
+
+  Notifier.notify(
+    <ProcessNotifyMessage title={title} desc={desc} onViewProcess={onViewProcess} success={success}/>,
+    null
+  );
+}
+
diff --git a/web/pgadmin/misc/bgprocess/static/js/ProcessDetails.jsx b/web/pgadmin/misc/bgprocess/static/js/ProcessDetails.jsx
new file mode 100644
index 000000000..22b5d16b5
--- /dev/null
+++ b/web/pgadmin/misc/bgprocess/static/js/ProcessDetails.jsx
@@ -0,0 +1,181 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import React, { useState, useMemo } from 'react';
+import gettext from 'sources/gettext';
+import url_for from 'sources/url_for';
+import { Box, makeStyles } from '@material-ui/core';
+import PropTypes from 'prop-types';
+import { MESSAGE_TYPE, NotifierMessage } from '../../../../static/js/components/FormComponents';
+import { BgProcessManagerProcessState } from './BgProcessManager';
+import { DefaultButton, PgIconButton } from '../../../../static/js/components/Buttons';
+import HighlightOffRoundedIcon from '@material-ui/icons/HighlightOffRounded';
+import AccessTimeRoundedIcon from '@material-ui/icons/AccessTimeRounded';
+import { useInterval } from '../../../../static/js/custom_hooks';
+import getApiInstance from '../../../../static/js/api_instance';
+import pgAdmin from 'sources/pgadmin';
+import FolderSharedRoundedIcon from '@material-ui/icons/FolderSharedRounded';
+
+
+const useStyles = makeStyles((theme)=>({
+  container: {
+    backgroundColor: theme.palette.background.default,
+    height: '100%',
+    display: 'flex',
+    flexDirection: 'column',
+    padding: '8px',
+    userSelect: 'text',
+  },
+  cmd: {
+    ...theme.mixins.panelBorder.all,
+    borderRadius: theme.shape.borderRadius,
+    backgroundColor: theme.otherVars.inputDisabledBg,
+    wordBreak: 'break-word',
+    margin: '8px 0px',
+    padding: '4px',
+  },
+  logs: {
+    flexGrow: 1,
+    borderRadius: theme.shape.borderRadius,
+    padding: '4px',
+    overflow: 'auto',
+    textOverflow: 'wrap-text',
+    margin: '8px 0px',
+    ...theme.mixins.panelBorder.all,
+  },
+  logErr: {
+    color: theme.palette.error.main,
+  },
+  terminateBtn: {
+    backgroundColor: theme.palette.error.main,
+    color: theme.palette.error.contrastText,
+    border: 0,
+    '&:hover': {
+      backgroundColor: theme.palette.error.dark,
+      color: theme.palette.error.contrastText,
+    },
+    '&.Mui-disabled': {
+      color: theme.palette.error.contrastText + ' !important',
+      border: 0,
+    }
+  }
+}));
+
+async function getDetailedStatus(api, jobId, out, err) {
+  let res = await api.get(url_for(
+    'bgprocess.detailed_status', {
+      'pid': jobId,
+      'out': out,
+      'err': err,
+    }
+  ));
+  return res.data;
+}
+
+export default function ProcessDetails({data}) {
+  const classes = useStyles();
+  const api = useMemo(()=>getApiInstance());
+  const [logs, setLogs] = useState(null);
+  const [completed, setCompleted] = useState(false);
+  const [[outPos, errPos], setOutErrPos] = useState([0, 0]);
+  const [exitCode, setExitCode] = useState(data.exit_code);
+  const [timeTaken, setTimeTaken] = useState(data.execution_time);
+
+  let notifyType = MESSAGE_TYPE.INFO;
+  let notifyText = gettext('Not started');
+
+  const process_state = pgAdmin.Browser.BgProcessManager.evaluateProcessState({
+    ...data,
+    exit_code: exitCode,
+  });
+
+  if(process_state == BgProcessManagerProcessState.PROCESS_STARTED) {
+    notifyText = gettext('Running...');
+  } else if(process_state == BgProcessManagerProcessState.PROCESS_FINISHED) {
+    notifyType = MESSAGE_TYPE.SUCCESS;
+    notifyText = gettext('Successfully completed.');
+  } else if(process_state == BgProcessManagerProcessState.PROCESS_FAILED) {
+    notifyType = MESSAGE_TYPE.ERROR;
+    notifyText = gettext('Failed (exit code: %s).', String(exitCode));
+  } else if(process_state == BgProcessManagerProcessState.PROCESS_TERMINATED) {
+    notifyType = MESSAGE_TYPE.ERROR;
+    notifyText = gettext('Terminated by user.');
+  } else if(process_state == BgProcessManagerProcessState.PROCESS_TERMINATING) {
+    notifyText = gettext('Terminating the process...');
+  }
+
+  useInterval(async ()=>{
+    const logsSortComp = (l1, l2)=>{
+      return l1[0].localeCompare(l2[0]);
+    };
+    let resData = await getDetailedStatus(api, data.id, outPos, errPos);
+    resData.out.lines.sort(logsSortComp);
+    resData.err.lines.sort(logsSortComp);
+    if(resData.out?.done && resData.err?.done && resData.exit_code != null) {
+      setExitCode(resData.exit_code);
+      setCompleted(true);
+    }
+    setTimeTaken(resData.execution_time);
+    setOutErrPos([resData.out.pos, resData.err.pos]);
+    setLogs((prevLogs)=>{
+      return [
+        ...(prevLogs || []),
+        ...resData.out.lines.map((l)=>l[1]),
+        ...resData.err.lines.map((l)=>l[1]),
+      ];
+    });
+
+  }, completed ? -1 : 1000);
+
+  const errRe = new RegExp(': (' + gettext('error') + '|' + gettext('fatal') + '):', 'i');
+  return (
+    <Box display="flex" flexDirection="column" className={classes.container}>
+      <Box>{data.details?.message}</Box>
+      {data.details?.cmd && <>
+        <Box>{gettext('Running command')}:</Box>
+        <Box className={classes.cmd}>{data.details.cmd}</Box>
+      </>}
+      {data.details?.query && <>
+        <Box>{gettext('Running query')}:</Box>
+        <Box className={classes.cmd}>{data.details.query}</Box>
+      </>}
+      <Box display="flex" justifyContent="space-between" alignItems="center" flexWrap="wrap">
+        <Box><span><AccessTimeRoundedIcon /> {gettext('Start time')}: {new Date(data.stime).toString()}</span></Box>
+        <Box>
+          {pgAdmin.server_mode == 'True' && data.current_storage_dir &&
+          <PgIconButton icon={<FolderSharedRoundedIcon />} title={gettext('Storage Manager')} onClick={()=>{
+            pgAdmin.Tools.FileManager.openStorageManager(data.current_storage_dir);
+          }} style={{marginRight: '4px'}} />}
+          <DefaultButton disabled={process_state != BgProcessManagerProcessState.PROCESS_STARTED} startIcon={<HighlightOffRoundedIcon />} className={classes.terminateBtn}>Stop Process</DefaultButton></Box>
+      </Box>
+      <Box flexGrow={1} className={classes.logs}>
+        {logs == null && gettext('Loading process logs...')}
+        {logs?.length == 0 && gettext('No logs available.')}
+        {logs?.map((log, i)=>{
+          return <div ref={(el)=>{
+            if(i==logs.length-1) {
+              el?.scrollIntoView();
+            }
+          }} key={i} className={errRe.test(log) ? classes.logErr : ''}>{log}</div>;
+        })}
+      </Box>
+      <Box display="flex" alignItems="center">
+        <NotifierMessage type={notifyType} message={notifyText} closable={false} textCenter={true} style={{flexGrow: 1, marginRight: '8px'}} />
+        <Box>{gettext('Execution time')}: {timeTaken} {gettext('seconds')}</Box>
+      </Box>
+    </Box>
+  );
+}
+
+ProcessDetails.propTypes = {
+  closeModal: PropTypes.func,
+  data: PropTypes.object,
+  onOK: PropTypes.func,
+  setHeight: PropTypes.func
+};
diff --git a/web/pgadmin/misc/bgprocess/static/js/Processes.jsx b/web/pgadmin/misc/bgprocess/static/js/Processes.jsx
new file mode 100644
index 000000000..c89c83667
--- /dev/null
+++ b/web/pgadmin/misc/bgprocess/static/js/Processes.jsx
@@ -0,0 +1,253 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import React, { useEffect } from 'react';
+import PgTable from 'sources/components/PgTable';
+import gettext from 'sources/gettext';
+import PropTypes from 'prop-types';
+import { makeStyles } from '@material-ui/core/styles';
+import pgAdmin from 'sources/pgadmin';
+import { BgProcessManagerEvents, BgProcessManagerProcessState } from './BgProcessManager';
+import { PgIconButton } from '../../../../static/js/components/Buttons';
+import CancelIcon from '@material-ui/icons/Cancel';
+import DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined';
+import DeleteIcon from '@material-ui/icons/Delete';
+import HelpIcon from '@material-ui/icons/HelpRounded';
+import url_for from 'sources/url_for';
+
+
+const useStyles = makeStyles((theme) => ({
+  stopButton: {
+    color: theme.palette.error.main
+  },
+  buttonClick: {
+    backgroundColor: theme.palette.grey[400]
+  },
+  emptyPanel: {
+    minHeight: '100%',
+    minWidth: '100%',
+    background: theme.otherVars.emptySpaceBg,
+    overflow: 'auto',
+    padding: '8px',
+    display: 'flex',
+  },
+  panelIcon: {
+    width: '80%',
+    margin: '0 auto',
+    marginTop: '25px !important',
+    position: 'relative',
+    textAlign: 'center',
+  },
+  panelMessage: {
+    marginLeft: '0.5rem',
+    fontSize: '0.875rem',
+  },
+  autoResizer: {
+    height: '100% !important',
+    width: '100% !important',
+    background: theme.palette.grey[400],
+    padding: '7.5px',
+    overflow: 'auto !important',
+    minHeight: '100%',
+    minWidth: '100%',
+  },
+}));
+
+
+const ProcessStateText = {
+  [BgProcessManagerProcessState.PROCESS_NOT_STARTED]: gettext('Not started'),
+  [BgProcessManagerProcessState.PROCESS_STARTED]: gettext('Running'),
+  [BgProcessManagerProcessState.PROCESS_FINISHED]: gettext('Finished'),
+  [BgProcessManagerProcessState.PROCESS_TERMINATED]: gettext('Terminated'),
+  [BgProcessManagerProcessState.PROCESS_TERMINATING]: gettext('Terminating...'),
+  [BgProcessManagerProcessState.PROCESS_FAILED]: gettext('Failed'),
+};
+
+export default function Processes() {
+  const classes = useStyles();
+  const [tableData, setTableData] = React.useState([]);
+
+  let columns = [
+    {
+      accessor: 'stop_process',
+      Header: () => null,
+      sortable: false,
+      resizable: false,
+      disableGlobalFilter: true,
+      width: 35,
+      maxWidth: 35,
+      minWidth: 35,
+      id: 'btn-stop',
+      // eslint-disable-next-line react/display-name
+      Cell: ({ row }) => {
+        return (
+          <PgIconButton
+            size="xs"
+            noBorder
+            icon={<CancelIcon />}
+            className={classes.stopButton}
+            disabled={row.original.process_state != BgProcessManagerProcessState.PROCESS_STARTED}
+            onClick={(e) => {
+              e.preventDefault();
+              pgAdmin.Browser.BgProcessManager.stopProcess(row.original.id);
+            }}
+            aria-label="Stop Process"
+            title={gettext('Stop Process')}
+          ></PgIconButton>
+        );
+      },
+    },
+    {
+      accessor: 'remove',
+      Header: () => null,
+      sortable: false,
+      resizable: false,
+      disableGlobalFilter: true,
+      width: 35,
+      maxWidth: 35,
+      minWidth: 35,
+      id: 'btn-remove',
+      // eslint-disable-next-line react/display-name
+      Cell: ({ row }) => {
+        return (
+          <PgIconButton
+            size="xs"
+            icon={<DeleteIcon />}
+            disabled={[BgProcessManagerProcessState.PROCESS_NOT_STARTED, BgProcessManagerProcessState.PROCESS_STARTED].includes(row.original.process_state)}
+            noBorder
+            onClick={(e) => {
+              e.preventDefault();
+              pgAdmin.Browser.BgProcessManager.acknowledge(row.original.id);
+            }}
+            aria-label="Acknowledge and Remove"
+            title={gettext('Acknowledge and Remove')}
+          />
+        );
+      },
+    },
+    {
+      accessor: 'view_details',
+      Header: () => null,
+      sortable: false,
+      resizable: false,
+      disableGlobalFilter: true,
+      width: 35,
+      maxWidth: 35,
+      minWidth: 35,
+      id: 'btn-logs',
+      // eslint-disable-next-line react/display-name
+      Cell: ({ row }) => {
+        return (
+          <PgIconButton
+            size="xs"
+            icon={<DescriptionOutlinedIcon />}
+            noBorder
+            onClick={(e) => {
+              e.preventDefault();
+              pgAdmin.Browser.BgProcessManager.viewJobDetails(row.original.id);
+            }}
+            aria-label="View details"
+            title={gettext('View details')}
+          />
+        );
+      },
+    },
+    {
+      Header: gettext('PID'),
+      accessor: 'utility_pid',
+      sortable: true,
+      resizable: false,
+      width: 70,
+      minWidth: 70,
+      disableGlobalFilter: false,
+    },
+    {
+      Header: gettext('Description'),
+      accessor: 'desc',
+      sortable: true,
+      resizable: true,
+      width: 500,
+      minWidth: 100,
+      disableGlobalFilter: false,
+    },
+    {
+      id: 'stime',
+      Header: gettext('Start Time'),
+      sortable: true,
+      resizable: true,
+      disableGlobalFilter: true,
+      width: 150,
+      minWidth: 150,
+      accessor: (row)=>(new Date(row.stime)),
+      Cell: ({row})=>(new Date(row.original.stime).toLocaleString()),
+    },
+    {
+      Header: gettext('Status'),
+      sortable: true,
+      resizable: false,
+      disableGlobalFilter: false,
+      width: 120,
+      minWidth: 120,
+      accessor: (row)=>ProcessStateText[row.process_state],
+    },
+    {
+      Header: gettext('Time Taken'),
+      accessor: 'execution_time',
+      sortable: true,
+      resizable: true,
+      disableGlobalFilter: true,
+    },
+  ];
+
+  const updateList = ()=>{
+    if(pgAdmin.Browser.BgProcessManager.procList) {
+      setTableData([...pgAdmin.Browser.BgProcessManager.procList]);
+    }
+  };
+
+  useEffect(() => {
+    updateList();
+    pgAdmin.Browser.BgProcessManager.registerListener(BgProcessManagerEvents.LIST_UPDATED, updateList);
+    return ()=>{
+      pgAdmin.Browser.BgProcessManager.deregisterListener(BgProcessManagerEvents.LIST_UPDATED, updateList);
+    };
+  }, []);
+
+  return (
+    <>
+      <PgTable
+        className={classes.autoResizer}
+        columns={columns}
+        data={tableData}
+        sortOptions={[{id: 'stime', desc: true}]}
+        CustomHeader={()=>{
+          return (
+            <PgIconButton
+              icon={<HelpIcon style={{fontSize: '1.2rem'}} />}
+              aria-label="Help"
+              title={gettext('Help')}
+              onClick={() => {
+                window.open(url_for('help.static', {'filename': 'processes.html'}));
+              }}
+            ></PgIconButton>
+          );
+        }}
+      ></PgTable>
+    </>
+  );
+}
+
+Processes.propTypes = {
+  res: PropTypes.array,
+  nodeData: PropTypes.object,
+  treeNodeInfo: PropTypes.object,
+  node: PropTypes.func,
+  item: PropTypes.object,
+  row: PropTypes.object,
+};
diff --git a/web/pgadmin/misc/bgprocess/static/js/bgprocess.js b/web/pgadmin/misc/bgprocess/static/js/bgprocess.js
deleted file mode 100644
index ddc965e7a..000000000
--- a/web/pgadmin/misc/bgprocess/static/js/bgprocess.js
+++ /dev/null
@@ -1,764 +0,0 @@
-/////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////
-
-define('misc.bgprocess', [
-  'sources/pgadmin', 'sources/gettext', 'sources/url_for', 'underscore',
-  'jquery', 'pgadmin.browser', 'alertify', 'pgadmin.tools.file_manager',
-], function(
-  pgAdmin, gettext, url_for, _, $, pgBrowser, Alertify
-) {
-
-  pgBrowser.BackgroundProcessObsorver = pgBrowser.BackgroundProcessObsorver || {};
-
-  if (pgBrowser.BackgroundProcessObsorver.initialized) {
-    return pgBrowser.BackgroundProcessObsorver;
-  }
-
-  var isServerMode = (function() { return pgAdmin.server_mode == 'True'; })();
-
-  var wcDocker = window.wcDocker;
-
-  var BGProcess = function(info, notify) {
-    var self = this;
-    setTimeout(
-      function() {
-        self.initialize.apply(self, [info, notify]);
-      }, 1
-    );
-  };
-
-  _.extend(
-    BGProcess.prototype, {
-      success_status_tpl: _.template(`
-      <div class="d-flex px-2 py-1 bg-success-light border border-success rounded">
-        <div class="pr-2">
-          <i class="fa fa-check text-success pg-bg-status-icon" aria-hidden="true" role="img"></i>
-        </div>
-        <div class="mx-auto pg-bg-status-text alert-text-body"><%-status_text%></div>
-      </div>`),
-      failed_status_tpl: _.template(`
-      <div class="d-flex px-2 py-1 bg-danger-lighter border border-danger rounded">
-        <div class="pr-2">
-          <i class="fa fa-times fa-lg text-danger pg-bg-status-icon" aria-hidden="true" role="img"></i>
-        </div>
-        <div class="mx-auto pg-bg-status-text alert-text-body"><%-status_text%></div>
-      </div>`),
-      other_status_tpl: _.template(`
-      <div class="d-flex px-2 py-1 bg-primary-light border border-primary rounded">
-        <div class="pr-2">
-          <i class="fa fa-info fa-lg text-primary pg-bg-status-icon" aria-hidden="true" role="img"></i>
-        </div>
-        <div class="mx-auto pg-bg-status-text alert-text-body"><%-status_text%></div>
-      </div>`),
-      initialize: function(info, notify) {
-        _.extend(this, {
-          details: false,
-          notify: (_.isUndefined(notify) || notify),
-          curr_status: null,
-          state: 0, // 0: NOT Started, 1: Started, 2: Finished, 3: Terminated
-          completed: false,
-          current_storage_dir: null,
-
-          id: info['id'],
-          type_desc: null,
-          desc: null,
-          detailed_desc: null,
-          stime: null,
-          exit_code: null,
-          acknowledge: info['acknowledge'],
-          execution_time: null,
-          out: -1,
-          err: -1,
-          lot_more: false,
-
-          notifier: null,
-          container: null,
-          panel: null,
-          logs: $('<ol></ol>', {
-            class: 'pg-bg-process-logs',
-          }),
-        });
-
-        if (this.notify) {
-          pgBrowser.Events && pgBrowser.Events.on(
-            'pgadmin-bgprocess:started:' + this.id,
-            function(process) {
-              if (!process.notifier)
-                process.show.apply(process);
-            }
-          );
-          pgBrowser.Events && pgBrowser.Events.on(
-            'pgadmin-bgprocess:finished:' + this.id,
-            function(process) {
-              if (!process.notifier) {
-                if (process.cloud_process == 1) process.update_cloud_server.apply(process);
-                process.show.apply(process);
-              }
-            }
-          );
-        }
-        var self = this;
-
-        setTimeout(
-          function() {
-            self.update.apply(self, [info]);
-          }, 1
-        );
-      },
-
-      bgprocess_url: function(type) {
-        switch (type) {
-        case 'status':
-          if (this.details && this.out != -1 && this.err != -1) {
-            return url_for(
-              'bgprocess.detailed_status', {
-                'pid': this.id,
-                'out': this.out,
-                'err': this.err,
-              }
-            );
-          }
-          return url_for('bgprocess.status', {
-            'pid': this.id,
-          });
-        case 'acknowledge':
-          return url_for('bgprocess.acknowledge', {
-            'pid': this.id,
-          });
-        case 'stop_process':
-          return url_for('bgprocess.stop_process', {
-            'pid': this.id,
-          });
-        default:
-          return url_for('bgprocess.list');
-        }
-      },
-
-      update: function(data) {
-        var self = this,
-          out = [],
-          err = [];
-
-        if ('stime' in data)
-          self.stime = new Date(data.stime);
-
-        if ('execution_time' in data)
-          self.execution_time = parseFloat(data.execution_time);
-
-        if ('type_desc' in data)
-          self.type_desc = data.type_desc;
-
-        if ('desc' in data)
-          self.desc = data.desc;
-
-        if ('details' in data)
-          self.detailed_desc = data.details;
-
-        if ('exit_code' in data)
-          self.exit_code = data.exit_code;
-
-        if ('process_state' in data)
-          self.state = data.process_state;
-
-        if ('current_storage_dir' in data)
-          self.current_storage_dir = data.current_storage_dir;
-
-        if ('out' in data) {
-          self.out = data.out && data.out.pos;
-
-          if (data.out && data.out.lines) {
-            out = data.out.lines;
-          }
-        }
-
-        if ('cloud_process' in data && data.cloud_process == 1) {
-          self.cloud_process = data.cloud_process;
-          self.cloud_instance = data.cloud_instance;
-          self.cloud_server_id = data.cloud_server_id;
-        }
-
-        if ('err' in data) {
-          self.err = data.err && data.err.pos;
-
-          if (data.err && data.err.lines) {
-            err = data.err.lines;
-          }
-        }
-        self.completed = self.completed || (
-          'err' in data && 'out' in data && data.err.done && data.out.done
-        ) || (!self.details && !_.isNull(self.exit_code));
-
-        var io = 0,
-          ie = 0,
-          res = [],
-          escapeEl = document.createElement('textarea'),
-          escapeHTML = function(html) {
-            escapeEl.textContent = html;
-            return escapeEl.innerHTML;
-          };
-
-        while (io < out.length && ie < err.length) {
-          if (pgAdmin.natural_sort(out[io][0], err[ie][0]) <= 0) {
-            res.push('<li class="pg-bg-res-out">' + escapeHTML(out[io++][1]) + '</li>');
-          } else {
-            let log_msg = escapeHTML(err[ie++][1]);
-            let regex_obj = new RegExp(': (' + gettext('error') + '|' + gettext('fatal') + '):', 'i');
-            if (regex_obj.test(log_msg)) {
-              res.push('<li class="pg-bg-res-err">' + log_msg + '</li>');
-            } else {
-              res.push('<li class="pg-bg-res-out">' + log_msg + '</li>');
-            }
-          }
-        }
-
-        while (io < out.length) {
-          res.push('<li class="pg-bg-res-out">' + escapeHTML(out[io++][1]) + '</li>');
-        }
-
-        while (ie < err.length) {
-          let log_msg = escapeHTML(err[ie++][1]);
-          let regex_obj = new RegExp(': (' + gettext('error') + '|' + gettext('fatal') + '):', 'i');
-          if (regex_obj.test(log_msg)) {
-            res.push('<li class="pg-bg-res-err">' + log_msg + '</li>');
-          } else {
-            res.push('<li class="pg-bg-res-out">' + log_msg + '</li>');
-          }
-        }
-
-        if (res.length) {
-          self.logs.append(res.join(''));
-          setTimeout(function() {
-            self.logs[0].scrollTop = self.logs[0].scrollHeight;
-          });
-        }
-
-        if(self.logs_loading) {
-          self.logs_loading.remove();
-          self.logs_loading = null;
-        }
-
-        if (self.stime) {
-          self.curr_status = self.other_status_tpl({status_text:gettext('Started')});
-
-          if (self.execution_time >= 2) {
-            self.curr_status = self.other_status_tpl({status_text:gettext('Running...')});
-          }
-
-          if (!_.isNull(self.exit_code)) {
-            if (self.state === 3) {
-              self.curr_status = self.failed_status_tpl({status_text:gettext('Terminated by user.')});
-            } else if (self.exit_code == 0) {
-              self.curr_status = self.success_status_tpl({status_text:gettext('Successfully completed.')});
-            } else {
-              self.curr_status = self.failed_status_tpl(
-                {status_text:gettext('Failed (exit code: %s).', String(self.exit_code))}
-              );
-            }
-          } else if (_.isNull(self.exit_code) && self.state === 3) {
-            self.curr_status = self.other_status_tpl({status_text:gettext('Terminating the process...')});
-          }
-
-          if (self.state == 0 && self.stime) {
-            self.state = 1;
-            pgBrowser.Events && pgBrowser.Events.trigger(
-              'pgadmin-bgprocess:started:' + self.id, self, self
-            );
-          }
-
-          if (self.state == 1 && !_.isNull(self.exit_code)) {
-            self.state = 2;
-            pgBrowser.Events && pgBrowser.Events.trigger(
-              'pgadmin-bgprocess:finished:' + self.id, self, self
-            );
-          }
-
-          setTimeout(function() {
-            self.show.apply(self);
-          }, 10);
-        }
-
-        if (!self.completed) {
-          setTimeout(
-            function() {
-              self.status.apply(self);
-            }, 1000
-          );
-        }
-      },
-
-      status: function() {
-        var self = this;
-
-        $.ajax({
-          typs: 'GET',
-          timeout: 30000,
-          url: self.bgprocess_url('status'),
-          cache: false,
-          async: true,
-          contentType: 'application/json',
-        })
-          .done(function(res) {
-            setTimeout(function() {
-              self.update(res);
-            }, 10);
-          })
-          .fail(function(res) {
-          // Try after some time only if job id present
-            if (res.status != 410)
-              setTimeout(function() {
-                self.update(res);
-              }, 10000);
-          });
-      },
-
-      update_cloud_server: function() {
-        var self = this,
-          _url = url_for('cloud.update_cloud_server'),
-          _data = {},
-          cloud_instance = self.cloud_instance;
-        if (cloud_instance != '') {
-          _data = JSON.parse(cloud_instance);
-        }
-
-        _data['instance']['sid'] = self.cloud_server_id;
-
-        $.ajax({
-          type: 'POST',
-          url: _url,
-          async: true,
-          data: JSON.stringify(_data),
-          contentType: 'application/json',
-        })
-          .done(function(res) {
-            setTimeout(function() {
-              let _server = res.data.node,
-                _server_path = '/browser/server_group_' + _server.gid + '/' + _server.id,
-                _tree = pgBrowser.tree,
-                _item = _tree.findNode(_server_path);
-
-              if (_item) {
-                _tree.addIcon(_item.domNode, {icon: _server.icon});
-                let d = _tree.itemData(_item);
-                d.cloud_status = 1;
-                _tree.update(_item, d);
-              }
-            }, 10);
-          })
-          .fail(function(res) {
-          // Try after some time only if job id present
-            if (res.status != 410)
-              console.warn('Failed Cloud Deployment.');
-          });
-      },
-
-      show: function() {
-        var self = this;
-
-        if (self.notify && !self.details) {
-          if (!self.notifier) {
-            let content = $(`
-            <div class="card">
-              <div class="card-header bg-primary d-flex">
-                <div>${self.type_desc}</div>
-                <div class="ml-auto">
-                  <button class="btn btn-sm-sq btn-primary pg-bg-close" aria-label='close'><i class="fa fa-lg fa-times" role="img"></i></button>
-                </div>
-              </div>
-              <div class="card-body px-2">
-                <div class="py-1">${self.desc}</div>
-                <div class="py-1">${self.stime.toString()}</div>
-                <div class="d-flex py-1">
-                  <div class="my-auto mr-2">
-                    <span class="fa fa-clock fa-lg" role="img"></span>
-                  </div>
-                  <div class="pg-bg-etime my-auto mr-2"></div>
-                  <div class="ml-auto">
-                    <button class="btn btn-secondary pg-bg-more-details" title="More Details"><span class="fa fa-info-circle" role="img"></span>&nbsp;` + gettext('More details...') + `</button>
-                    <button class="btn btn-danger bg-process-stop" disabled><span class="fa fa-times-circle" role="img" title="Stop the operation"></span>&nbsp;` + gettext('Stop Process') + `</button>
-                  </div>
-                </div>
-                <div class="pg-bg-status py-1">
-                </div>
-              </div>
-            </div>
-            `);
-
-            let for_details = content.find('.pg-bg-more-details');
-            let close_me = content.find('.pg-bg-close');
-
-            self.container = content;
-            self.notifier = Alertify.notify(
-              content.get(0), 'bg-bgprocess', 0, null
-            );
-
-            for_details.on('click', function(ev) {
-              ev = ev || window.event;
-              ev.cancelBubble = true;
-              ev.stopPropagation();
-
-              this.notifier.dismiss();
-              this.notifier = null;
-              this.completed = false;
-
-              this.show_detailed_view.apply(this);
-            }.bind(self));
-
-            close_me.on('click', function() {
-              this.notifier.dismiss();
-              this.notifier = null;
-              this.acknowledge_server.apply(this);
-            }.bind(this));
-
-            // Do not close the notifier, when clicked on the container, which
-            // is a default behaviour.
-            self.container.on('click', function(ev) {
-              ev = ev || window.event;
-              ev.cancelBubble = true;
-              ev.stopPropagation();
-            });
-
-            // On Click event to stop the process.
-            content.find('.bg-process-stop').off('click').on('click', self.stop_process.bind(this));
-          }
-
-          // TODO:: Formatted execution time
-          self.container.find('.pg-bg-etime').empty().append(
-            $('<span></span>').text(
-              String(self.execution_time)
-            )
-          ).append(
-            $('<span></span>').text(' ' + gettext('seconds'))
-          );
-
-          var $status_bar = $(self.container.find('.pg-bg-status'));
-          $status_bar.html(self.curr_status);
-          var $btn_stop_process = $(self.container.find('.bg-process-stop'));
-
-          // Enable Stop Process button only when process is running
-          if (parseInt(self.state) === 1) {
-            $btn_stop_process.attr('disabled', false);
-          } else {
-            $btn_stop_process.attr('disabled', true);
-          }
-        } else {
-          self.show_detailed_view.apply(self);
-        }
-      },
-
-      show_detailed_view: function() {
-        var self = this,
-          panel = this.panel,
-          is_new = false;
-
-        if (!self.panel) {
-          is_new = true;
-          panel = this.panel =
-            pgBrowser.BackgroundProcessObsorver.create_panel();
-          panel.title(gettext('Process Watcher - %s', self.type_desc));
-          panel.focus();
-        }
-
-        var container = panel.$container,
-          $logs = container.find('.bg-process-watcher'),
-          $header = container.find('.bg-process-details'),
-          $footer = container.find('.bg-process-footer'),
-          $btn_stop_process = container.find('.bg-process-stop'),
-          $btn_storage_manager = container.find('.bg-process-storage-manager');
-
-        if(self.current_storage_dir && isServerMode) { //for backup & exports with server mode, operate over storage manager
-
-          if($btn_storage_manager.length == 0) {
-            var str_storage_manager_btn = '<button id="bg-process-storage-manager" class="btn btn-secondary bg-process-storage-manager" title="Click to open file location" aria-label="Storage Manager" tabindex="0" disabled><span class="pg-font-icon icon-storage_manager" role="img"></span></button>&nbsp;';
-            container.find('.bg-process-details .bg-btn-section').prepend(str_storage_manager_btn);
-            $btn_storage_manager = container.find('.bg-process-storage-manager');
-          }
-
-          // Disable storage manager button only when process is running
-          if (parseInt(self.state) === 1) {
-            $btn_storage_manager.attr('disabled', true);
-          }
-          else {
-            $btn_storage_manager.attr('disabled', false);
-          }
-          // On Click event for storage manager button.
-          $btn_storage_manager.off('click').on('click', self.storage_manager.bind(this));
-        }
-
-        // Enable Stop Process button only when process is running
-        if (parseInt(self.state) === 1) {
-          $btn_stop_process.attr('disabled', false);
-        } else {
-          $btn_stop_process.attr('disabled', true);
-        }
-
-        // On Click event to stop the process.
-        $btn_stop_process.off('click').on('click', self.stop_process.bind(this));
-
-        if (is_new) {
-          // set logs
-          $logs.html(self.logs);
-          setTimeout(function() {
-            self.logs[0].scrollTop = self.logs[0].scrollHeight;
-          });
-          self.logs_loading = $('<li class="pg-bg-res-out loading-logs">' + gettext('Loading process logs...') + '</li>');
-          self.logs.append(self.logs_loading);
-          // set bgprocess detailed description
-          $header.find('.bg-detailed-desc').html(self.detailed_desc);
-        }
-
-        // set bgprocess start time
-        $header.find('.bg-process-stats .bgprocess-start-time').html(
-          self.stime
-        );
-
-        // set status
-        $footer.find('.bg-process-status').html(self.curr_status);
-
-        // set bgprocess execution time
-        $footer.find('.bg-process-exec-time p').empty().append(
-          $('<span></span>').text(
-            String(self.execution_time)
-          )
-        ).append(
-          $('<span></span>').text(' ' + gettext('seconds'))
-        );
-
-        if (is_new) {
-          self.details = true;
-          self.err = 0;
-          self.out = 0;
-          setTimeout(
-            function() {
-              self.status.apply(self);
-            }, 1000
-          );
-
-          var resize_log_container = function(logs, header, footer) {
-            var h = header.outerHeight() + footer.outerHeight();
-            logs.css('padding-bottom', h);
-          }.bind(panel, $logs, $header, $footer);
-
-          panel.on(wcDocker.EVENT.RESIZED, resize_log_container);
-          panel.on(wcDocker.EVENT.ATTACHED, resize_log_container);
-          panel.on(wcDocker.EVENT.DETACHED, resize_log_container);
-
-          resize_log_container();
-
-          panel.on(wcDocker.EVENT.CLOSED, function(process) {
-            process.panel = null;
-
-            process.details = false;
-            if (process.exit_code != null) {
-              process.acknowledge_server.apply(process);
-            }
-          }.bind(panel, this));
-        }
-      },
-
-      acknowledge_server: function() {
-        var self = this;
-        $.ajax({
-          type: 'PUT',
-          timeout: 30000,
-          url: self.bgprocess_url('acknowledge'),
-          cache: false,
-          async: true,
-          contentType: 'application/json',
-        })
-          .done(function(res) {
-            if (res.data && res.data.node) {
-              setTimeout(function() {
-                let _server = res.data.node,
-                  _server_path = '/browser/server_group_' + _server.gid + '/' + _server.id,
-                  _tree = pgBrowser.tree,
-                  _item = _tree.findNode(_server_path);
-
-                if (_item) {
-                  if(_server.status == true) {
-                    let _dom = _item.domNode;
-                    _tree.addIcon(_dom, {icon: _server.icon});
-                    let d = _tree.itemData(_dom);
-                    d.cloud_status = _server.cloud_status;
-                    _tree.update(_dom, d);
-                  }
-                  else {
-                    _tree.remove(_item.domNode);
-                    _tree.refresh(_item.domNode.parent);
-                  }
-                }
-
-              }, 10);
-            } else return;
-          })
-          .fail(function() {
-            console.warn(arguments);
-          });
-      },
-
-      stop_process: function() {
-        var self = this;
-        // Set the state to terminated.
-        self.state = 3;
-        $.ajax({
-          type: 'PUT',
-          timeout: 30000,
-          url: self.bgprocess_url('stop_process'),
-          cache: false,
-          async: true,
-          contentType: 'application/json',
-        })
-          .done(function() {
-            return;
-          })
-          .fail(function() {
-            console.warn(arguments);
-          });
-      },
-
-      storage_manager: function() {
-
-        var self = this;
-        if(self.current_storage_dir) {
-          pgAdmin.Tools.FileManager.openStorageManager(self.current_storage_dir);
-        }
-      },
-    });
-
-  _.extend(
-    pgBrowser.BackgroundProcessObsorver, {
-      bgprocesses: {},
-      init: function() {
-        var self = this;
-
-        if (self.initialized) {
-          return;
-        }
-        self.initialized = true;
-
-        setTimeout(
-          function() {
-            self.update_process_list.apply(self);
-          }, 1000
-        );
-
-        pgBrowser.Events.on(
-          'pgadmin-bgprocess:created',
-          function() {
-            setTimeout(
-              function() {
-                pgBrowser.BackgroundProcessObsorver.update_process_list(true);
-              }, 1000
-            );
-          }
-        );
-      },
-
-      update_process_list: function(recheck) {
-        var observer = this;
-
-        $.ajax({
-          type: 'GET',
-          timeout: 30000,
-          url: url_for('bgprocess.list'),
-          cache: false,
-          async: true,
-          contentType: 'application/json',
-        })
-          .done(function(res) {
-            if (!res || !_.isArray(res)) {
-              return;
-            }
-            for (var idx in res) {
-              var process = res[idx];
-              if ('id' in process) {
-                if (!(process.id in observer.bgprocesses)) {
-                  observer.bgprocesses[process.id] = new BGProcess(process);
-                }
-              }
-            }
-            if (recheck && res.length == 0) {
-            // Recheck after some more time
-              setTimeout(
-                function() {
-                  observer.update_process_list(false);
-                }, 3000
-              );
-            }
-          })
-          .fail(function() {
-          // FIXME:: What to do now?
-            console.warn(arguments);
-          });
-      },
-
-      create_panel: function() {
-        this.register_panel();
-
-        return pgBrowser.docker.addPanel(
-          'bg_process_watcher',
-          wcDocker.DOCK.FLOAT,
-          null, {
-            w: (screen.width < 700 ?
-              screen.width * 0.95 : screen.width * 0.5),
-            h: (screen.height < 500 ?
-              screen.height * 0.95 : screen.height * 0.5),
-            x: (screen.width < 700 ? '2%' : '25%'),
-            y: (screen.height < 500 ? '2%' : '25%'),
-          });
-      },
-
-      register_panel: function() {
-        var w = pgBrowser.docker,
-          panels = w.findPanels('bg_process_watcher');
-
-        if (panels && panels.length >= 1)
-          return;
-
-        var p = new pgBrowser.Panel({
-          name: 'bg_process_watcher',
-          showTitle: true,
-          isCloseable: true,
-          isPrivate: true,
-          isLayoutMember: false,
-          content: '<div class="bg-process-details">' +
-              '<div class="bg-detailed-desc"></div>' +
-              '<div class="bg-process-stats d-flex py-1">' +
-                '<div class="my-auto mr-2">' +
-                  '<span class="fa fa-clock fa-lg" role="img"></span>' +
-                '</div>' +
-                '<div class="pg-bg-etime my-auto mr-2">'+
-                  '<span>' + gettext('Start time') + ': <span class="bgprocess-start-time"></span>' +
-                  '</span>'+
-                '</div>' +
-                '<div class="ml-auto bg-btn-section">' +
-                  '<button type="button" class="btn btn-danger bg-process-stop" disabled><span class="fa fa-times-circle" role="img"></span>&nbsp;' + gettext('Stop Process') + '</button>' +
-                '</div>' +
-              '</div>' +
-            '</div>' +
-            '<div class="bg-process-watcher">' +
-            '</div>' +
-            '<div class="bg-process-footer p-2 d-flex">' +
-              '<div class="bg-process-status flex-grow-1">' +
-              '</div>' +
-              '<div class="bg-process-exec-time ml-4 my-auto">' +
-                '<div class="exec-div">' +
-                  '<span>' + gettext('Execution time') + ':</span><p></p>' +
-                '</div>' +
-              '</div>' +
-            '</div>',
-          onCreate: function(myPanel, $container) {
-            $container.addClass('pg-no-overflow p-2');
-          },
-        });
-        p.load(pgBrowser.docker);
-      },
-    });
-
-  return pgBrowser.BackgroundProcessObsorver;
-});
diff --git a/web/pgadmin/misc/bgprocess/static/js/index.js b/web/pgadmin/misc/bgprocess/static/js/index.js
new file mode 100644
index 000000000..b1dd50475
--- /dev/null
+++ b/web/pgadmin/misc/bgprocess/static/js/index.js
@@ -0,0 +1,22 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+import pgAdmin from 'sources/pgadmin';
+import pgBrowser from 'top/browser/static/js/browser';
+import BgProcessManager from './BgProcessManager';
+
+if (!pgAdmin.Browser) {
+  pgAdmin.Browser = {};
+}
+
+pgAdmin.Browser.BgProcessManager = BgProcessManager.getInstance(pgBrowser);
+
+module.exports = {
+  BgProcessManager: BgProcessManager,
+};
+
diff --git a/web/pgadmin/misc/bgprocess/static/js/showDetails.jsx b/web/pgadmin/misc/bgprocess/static/js/showDetails.jsx
new file mode 100644
index 000000000..5d2af220e
--- /dev/null
+++ b/web/pgadmin/misc/bgprocess/static/js/showDetails.jsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import pgAdmin from 'sources/pgadmin';
+import Theme from '../../../../static/js/Theme';
+import ProcessDetails from './ProcessDetails';
+import gettext from 'sources/gettext';
+
+export default function showDetails(p) {
+  let pgBrowser = pgAdmin.Browser;
+
+  // Register dialog panel
+  pgBrowser.Node.registerUtilityPanel();
+  let panel = pgBrowser.Node.addUtilityPanel(pgBrowser.stdW.md),
+    j = panel.$container.find('.obj_properties').first();
+  panel.title(gettext('Process Watcher - %s', p.type_desc));
+  panel.focus();
+
+  panel.on(window.wcDocker.EVENT.CLOSED, ()=>{
+    ReactDOM.unmountComponentAtNode(j[0]);
+  });
+
+  ReactDOM.render(
+    <Theme>
+      <ProcessDetails
+        data={p}
+        closeModal={()=>{
+          panel.close();
+        }}
+      />
+    </Theme>, j[0]);
+}
diff --git a/web/pgadmin/misc/bgprocess/static/scss/_bgprocess.scss b/web/pgadmin/misc/bgprocess/static/scss/_bgprocess.scss
deleted file mode 100644
index 016e44842..000000000
--- a/web/pgadmin/misc/bgprocess/static/scss/_bgprocess.scss
+++ /dev/null
@@ -1,127 +0,0 @@
-$bgproc-container-pad: 2px;
-
-
-.ajs-bg-bgprocess.ajs-visible {
-  border: none;
-  padding: 0px !important;
-  text-align: left;
-  color: $color-fg;
-  min-width: 500px;
-  max-width: 500px;
-  .card {
-    border:none;
-    & .card-header {
-      border: $border-width solid $color-primary;
-      background: $color-primary;
-      color: $color-primary-fg;
-    }
-
-    & .card-body {
-      padding: 5px;
-      border: $border-width solid $card-border-color;
-      border-bottom-left-radius: $card-border-radius;
-      border-bottom-right-radius: $card-border-radius;
-    }
-  }
-}
-
-
-.ajs-bg-bgprocess > .pg-bg-bgprocess {
-  background-color: $color-primary;
-  color: $color-primary-fg;
-  padding: $bgproc-container-pad;
-  text-align: left;
-  font-size: 0.9em;
-}
-
-.ajs-bg-bgprocess > .pg-bg-bgprocess > .pg-bg-notify-header {
-  background-color:  $color-gray-dark;
-  margin: (-$bgproc-container-pad) (-$bgproc-container-pad) 5px;
-  padding: 5px;
-  padding-right: 20px;
-  white-space: pre-wrap;
-  text-align: center;
-  border-top-left-radius: 5px;
-  border-top-right-radius: 5px;
-}
-
-.ajs-bg-bgprocess > .pg-bg-bgprocess > .pg-bg-notify-body {
-  font-family: $font-family-editor;
-  white-space: nowrap;
-  padding: 5px 0px;
-}
-
-.pg-bg-click {
-  color: $color-gray-lighter;
-  text-decoration: underline;
-  cursor: pointer;
-  padding: 5px 0px;
-}
-
-.pg-bg-click:hover {
-  color:  $color-gray-dark;
-}
-
-.pg-bg-res-out, .pg-bg-res-err {
-  white-space: pre-wrap;
-}
-
-.pg-bg-res-err {
-  color: $color-danger;
-}
-
-
-.ajs-bg-bgprocess > .pg-bg-bgprocess > .pg-bg-status.bg-success,
-.bg-process-status .bg-bgprocess-success {
-  color: $color-success-light;
-  font-weight: bold;
-}
-
-.bg-process-status .bg-bgprocess-failed {
-  color: $color-danger;
-  font-weight: bold;
-}
-
-.ajs-bg-bgprocess > .pg-bg-bgprocess > .pg-bg-status.bg-failed {
-  color: $color-fg;
-  background-color: $color-danger-lighter;
-}
-
-.pg-panel-content div.bg-process-watcher {
-  height: 100%;
-  padding: 0px 0px 0px 0px;
-}
-
-.pg-bg-process-logs {
-  border: $border-width solid $input-border-color;
-  border-radius: $input-border-radius;
-  padding-inline-start: 1rem;
-}
-
-.pg-bg-cmd {
-  border: $border-width solid $input-border-color;
-  border-radius: $input-border-radius;
-  background: $input-disabled-bg;
-  word-break: break-word;
-}
-
-.pg-panel-content .bg-process-footer {
-  position: absolute;
-  bottom: 0;
-  right: 0px;
-  left: 0px;
-}
-
-.pg-bg-bgprocess .bg-close {
-  display: inline-block;
-  position: relative;
-  height: 25px;
-  width: 25px;
-  right: -12px;
-  padding: 2px;
-  border: 2px solid $color-primary;
-  border-radius: 4px;
-  opacity: 0.5;
-  background-color: $color-bg;
-  color: $color-danger;
-}
diff --git a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
index 2255d6afc..eba8ef3e2 100644
--- a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
+++ b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
@@ -153,7 +153,7 @@ export default function CloudWizard({ nodeInfo, nodeData, onClose}) {
     axiosApi.post(_url, post_data)
       .then((res) => {
         pgAdmin.Browser.Events.trigger('pgadmin:browser:tree:add', res.data.data.node, {'server_group': nodeInfo['server_group']});
-        pgAdmin.Browser.Events.trigger('pgadmin-bgprocess:created');
+        pgAdmin.Browser.BgProcessManager.startProcess(res.data.data.job_id, res.data.data.desc);
         onClose();
       })
       .catch((error) => {
diff --git a/web/pgadmin/misc/cloud/utils/__init__.py b/web/pgadmin/misc/cloud/utils/__init__.py
index 6d91ad8c3..0ee02a5e2 100644
--- a/web/pgadmin/misc/cloud/utils/__init__.py
+++ b/web/pgadmin/misc/cloud/utils/__init__.py
@@ -79,13 +79,10 @@ class CloudProcessDesc(IProcessDesc):
             self.provider, self.instance_name))
 
     def details(self, cmd, args):
-        res = '<div>' + self.message
-        res += '</div><div class="py-1">'
-        res += '<div class="pg-bg-cmd enable-selection p-1">'
-        res += html.safe_str(self.cmd)
-        res += '</div></div>'
-
-        return res
+        return {
+            "message": self.message,
+            "cmd": self.cmd
+        }
 
     @property
     def type_desc(self):
diff --git a/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx b/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx
index b4e0f0b19..7a23b0eca 100644
--- a/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx
+++ b/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx
@@ -80,21 +80,21 @@ export default function Dependencies({ nodeData, item, node, ...props }) {
     {
       Header: 'Type',
       accessor: 'type',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       Header: 'Name',
       accessor: 'name',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       Header: 'Restriction',
       accessor: 'field',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 280,
diff --git a/web/pgadmin/misc/dependents/static/js/Dependents.jsx b/web/pgadmin/misc/dependents/static/js/Dependents.jsx
index ef43ce79a..0c54c36cf 100644
--- a/web/pgadmin/misc/dependents/static/js/Dependents.jsx
+++ b/web/pgadmin/misc/dependents/static/js/Dependents.jsx
@@ -81,21 +81,21 @@ export default function Dependents({ nodeData, item, node, ...props }) {
     {
       Header: 'Type',
       accessor: 'type',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       Header: 'Name',
       accessor: 'name',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       Header: 'Restriction',
       accessor: 'field',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 280,
diff --git a/web/pgadmin/misc/properties/CollectionNodeProperties.jsx b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx
index c4550ee7e..1691d4139 100644
--- a/web/pgadmin/misc/properties/CollectionNodeProperties.jsx
+++ b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx
@@ -99,14 +99,14 @@ export function CollectionNodeView({
     {
       Header: 'properties',
       accessor: 'Properties',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       Header: 'value',
       accessor: 'value',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
@@ -209,7 +209,7 @@ export function CollectionNodeView({
               column = {
                 Header: field.label,
                 accessor: field.id,
-                sortble: true,
+                sortable: true,
                 resizable: true,
                 disableGlobalFilter: false,
                 minWidth: 0,
@@ -222,7 +222,7 @@ export function CollectionNodeView({
               column = {
                 Header: field.label,
                 accessor: field.id,
-                sortble: true,
+                sortable: true,
                 resizable: true,
                 disableGlobalFilter: false,
                 minWidth: 0,
@@ -236,7 +236,7 @@ export function CollectionNodeView({
           column = {
             Header: field,
             accessor: field,
-            sortble: true,
+            sortable: true,
             resizable: true,
             disableGlobalFilter: false,
             minWidth: 0,
@@ -267,7 +267,7 @@ export function CollectionNodeView({
     }
   }, [itemNodeData, node, item, reload]);
 
-  const customHeader = () => {
+  const CustomHeader = () => {
     return (
       <Box >
         <PgIconButton
@@ -308,7 +308,7 @@ export function CollectionNodeView({
           (
             <PgTable
               isSelectRow={!('catalog' in treeNodeInfo) && (itemNodeData.label !== 'Catalogs') && _.isUndefined(node?.canSelect)}
-              customHeader={customHeader}
+              CustomHeader={CustomHeader}
               className={classes.autoResizer}
               columns={pgTableColumns}
               data={data}
diff --git a/web/pgadmin/misc/statistics/static/js/Statistics.jsx b/web/pgadmin/misc/statistics/static/js/Statistics.jsx
index fedd7ef59..3c450caef 100644
--- a/web/pgadmin/misc/statistics/static/js/Statistics.jsx
+++ b/web/pgadmin/misc/statistics/static/js/Statistics.jsx
@@ -60,7 +60,7 @@ function getColumn(data, singleLineStatistics) {
           column = {
             Header: row.name,
             accessor: row.name,
-            sortble: true,
+            sortable: true,
             resizable: true,
             disableGlobalFilter: false,
             sortType: ((rowA, rowB, id) => {
@@ -92,7 +92,7 @@ function getColumn(data, singleLineStatistics) {
           column = {
             Header: row.name,
             accessor: row.name,
-            sortble: true,
+            sortable: true,
             resizable: true,
             disableGlobalFilter: false,
           };
@@ -107,14 +107,14 @@ function getColumn(data, singleLineStatistics) {
       {
         Header: gettext('Statistics'),
         accessor: 'name',
-        sortble: true,
+        sortable: true,
         resizable: true,
         disableGlobalFilter: false,
       },
       {
         Header: 'Value',
         accessor: 'value',
-        sortble: true,
+        sortable: true,
         resizable: true,
         disableGlobalFilter: false,
       },
@@ -185,14 +185,14 @@ export default function Statistics({ nodeData, item, node, ...props }) {
     {
       Header: 'Statictics',
       accessor: 'name',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
     {
       Header: 'Value',
       accessor: 'value',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
     },
diff --git a/web/pgadmin/static/js/api_instance.js b/web/pgadmin/static/js/api_instance.js
index 4a4c65467..fdeb108bb 100644
--- a/web/pgadmin/static/js/api_instance.js
+++ b/web/pgadmin/static/js/api_instance.js
@@ -14,14 +14,13 @@ import axios from 'axios';
 /* Get the axios instance to call back end APIs.
 Do not import axios directly, instead use this */
 export default function getApiInstance(headers={}) {
-  const api = axios.create({
+  return axios.create({
     headers: {
       'Content-type': 'application/json',
       [pgAdmin.csrf_token_header]: pgAdmin.csrf_token,
       ...headers,
     }
   });
-  return api;
 }
 
 export function parseApiError(error) {
diff --git a/web/pgadmin/static/js/components/Buttons.jsx b/web/pgadmin/static/js/components/Buttons.jsx
index c446926c5..27dabf998 100644
--- a/web/pgadmin/static/js/components/Buttons.jsx
+++ b/web/pgadmin/static/js/components/Buttons.jsx
@@ -81,6 +81,17 @@ const useStyles = makeStyles((theme)=>({
   },
   noBorder: {
     border: 0,
+    color: 'inherit',
+    backgroundColor: 'transparent',
+    '&:hover': {
+      border: 0,
+      color: 'inherit',
+      backgroundColor: 'inherit',
+      filter: 'brightness(85%)',
+    },
+    '&.Mui-disabled': {
+      border: 0,
+    },
   }
 }));
 
diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx
index 6b72869df..c925ec94a 100644
--- a/web/pgadmin/static/js/components/FormComponents.jsx
+++ b/web/pgadmin/static/js/components/FormComponents.jsx
@@ -1167,6 +1167,7 @@ const useStylesFormFooter = makeStyles((theme) => ({
     padding: theme.spacing(0.5),
     display: 'flex',
     alignItems: 'center',
+    minHeight: '36px',
   },
   containerSuccess: {
     borderColor: theme.palette.success.main,
@@ -1290,11 +1291,13 @@ FormInputSelectThemes.propTypes = {
 };
 
 
-export function NotifierMessage({ type = MESSAGE_TYPE.SUCCESS, message, closable = true, showIcon=true, textCenter=false, onClose = () => {/*This is intentional (SonarQube)*/ } }) {
+export function NotifierMessage({
+  type = MESSAGE_TYPE.SUCCESS, message, style, closable = true, showIcon=true, textCenter=false,
+  onClose = () => {/*This is intentional (SonarQube)*/ }}) {
   const classes = useStylesFormFooter();
 
   return (
-    <Box className={clsx(classes.container, classes[`container${type}`])}>
+    <Box className={clsx(classes.container, classes[`container${type}`])} style={style}>
       {showIcon && <FormIcon type={type} className={classes[`icon${type}`]} />}
       <Box className={textCenter ? classes.messageCenter : classes.message}>{HTMLReactParse(message || '')}</Box>
       {closable && <IconButton className={clsx(classes.closeButton, classes[`icon${type}`])} onClick={onClose}>
@@ -1311,6 +1314,7 @@ NotifierMessage.propTypes = {
   showIcon: PropTypes.bool,
   textCenter: PropTypes.bool,
   onClose: PropTypes.func,
+  style: PropTypes.object,
 };
 
 
diff --git a/web/pgadmin/static/js/components/PgTable.jsx b/web/pgadmin/static/js/components/PgTable.jsx
index dca323fcc..ef151b83d 100644
--- a/web/pgadmin/static/js/components/PgTable.jsx
+++ b/web/pgadmin/static/js/components/PgTable.jsx
@@ -28,6 +28,8 @@ import _ from 'lodash';
 import gettext from 'sources/gettext';
 import SchemaView from '../SchemaView';
 import EmptyPanelMessage from './EmptyPanelMessage';
+import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
+import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
 
 /* eslint-disable react/display-name */
 const useStyles = makeStyles((theme) => ({
@@ -50,31 +52,18 @@ const useStyles = makeStyles((theme) => ({
     overflowX: 'hidden !important',
     overflow: 'overlay !important',
   },
-  customHeader:{
+  CustomHeader:{
     marginTop: '8px',
     marginLeft: '4px'
   },
-  searchBox: {
-    display: 'flex',
-    background: theme.palette.background.default
-  },
   warning: {
     backgroundColor: theme.palette.warning.main + '!important'
   },
   alert: {
     backgroundColor: theme.palette.error.main + '!important'
   },
-  searchPadding: {
-    flex: 2.5
-  },
   searchInput: {
-    flex: 1,
-    marginTop: 8,
-    borderLeft: 'none',
-    paddingLeft: 5,
-    marginRight: 8,
-    marginBottom: 8,
-
+    minWidth: '300px'
   },
   tableContainer: {
     overflowX: 'auto',
@@ -93,14 +82,18 @@ const useStyles = makeStyles((theme) => ({
     flexDirection: 'column',
     height: '100%',
   },
-  pgTableHeadar: {
+  pgTableContainer: {
     display: 'flex',
     flexGrow: 1,
-    overflow: 'hidden !important',
-    height: '100% !important',
-    flexDirection: 'column'
+    overflow: 'hidden',
+    flexDirection: 'column',
+    height: '100%',
+  },
+  pgTableHeader: {
+    display: 'flex',
+    background: theme.palette.background.default,
+    padding: '8px',
   },
-
   tableRowContent:{
     display: 'flex',
     flexDirection: 'column',
@@ -138,6 +131,7 @@ const useStyles = makeStyles((theme) => ({
     overflowX: 'hidden',
     alignContent: 'center',
     backgroundColor: theme.otherVars.tableBg,
+    overflow: 'hidden',
     ...theme.mixins.panelBorder.bottom,
     ...theme.mixins.panelBorder.right,
     ...theme.mixins.panelBorder.top,
@@ -221,7 +215,7 @@ IndeterminateCheckbox.propTypes = {
 };
 
 const ROW_HEIGHT = 35;
-export default function PgTable({ columns, data, isSelectRow, caveTable=true, ...props }) {
+export default function PgTable({ columns, data, isSelectRow, caveTable=true, schema, ExpandedComponent, sortOptions, ...props }) {
   // Use the state and functions returned from useTable to build your UI
   const classes = useStyles();
   const [searchVal, setSearchVal] = React.useState('');
@@ -277,6 +271,9 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
       defaultColumn,
       isSelectRow,
       autoResetSortBy: false,
+      initialState: {
+        sortBy: sortOptions || [],
+      }
     },
     useGlobalFilter,
     useSortBy,
@@ -333,7 +330,7 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
                   />
                 </div>
               ),
-              sortble: false,
+              sortable: false,
               width: 35,
               maxWidth: 35,
               minWidth: 0
@@ -421,7 +418,7 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
                   classNames.push(classes.alert);
                 }
                 return (
-                  <div key={cell.column.id} {...cell.getCellProps()} className={clsx(classNames, row.original.icon && row.original.icon[cell.column.id], row.original.icon[cell.column.id] && classes.cellIcon)}
+                  <div key={cell.column.id} {...cell.getCellProps()} className={clsx(classNames, row.original.icon?.[cell.column.id], row.original.icon?.[cell.column.id] && classes.cellIcon)}
                     title={_.isUndefined(cell.value) || _.isNull(cell.value) ? '': String(cell.value)}>
                     {cell.render('Cell')}
                   </div>
@@ -430,13 +427,14 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
             </div>
             {!_.isUndefined(row) && row.isExpanded && (
               <Box key={row.id} className={classes.expandedForm}>
-                <SchemaView
+                {schema && <SchemaView
                   getInitData={()=>Promise.resolve({})}
                   viewHelperProps={{ mode: 'properties' }}
-                  schema={props.schema[row.id]}
+                  schema={schema[row.id]}
                   showFooter={false}
                   onDataChange={()=>{setExpandComplete(true);}}
-                />
+                />}
+                {ExpandedComponent && <ExpandedComponent row={row} onExpandComplete={()=>setExpandComplete(true)}/>}
               </Box>
             )}
           </div>
@@ -447,24 +445,30 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
   );
   // Render the UI for your table
   return (
-    <Box className={classes.pgTableHeadar}>
-      <Box className={classes.searchBox}>
-        {props.customHeader && (<Box className={classes.customHeader}> <props.customHeader /></Box>)}
-        <Box className={classes.searchPadding}></Box>
-        <InputText
-          placeholder={'Search'}
-          className={classes.searchInput}
-          value={searchVal}
-          onChange={(val) => {
-            setSearchVal(val);
-          }}
-        />
+    <Box className={classes.pgTableContainer}>
+      <Box className={classes.pgTableHeader}>
+        {props.CustomHeader && (<Box className={classes.customHeader}> <props.CustomHeader /></Box>)}
+        <Box marginLeft="auto">
+          <InputText
+            placeholder={'Search'}
+            className={classes.searchInput}
+            value={searchVal}
+            onChange={(val) => {
+              setSearchVal(val);
+            }}
+          />
+        </Box>
       </Box>
       <div className={classes.tableContainer}>
         <div {...getTableProps({style:{minWidth: totalColumnsWidth}})} className={clsx(classes.table, caveTable ? classes.caveTable : '')}>
           <div>
             {headerGroups.map((headerGroup) => (
-              <div key={''} {...headerGroup.getHeaderGroupProps()}>
+              <div key={''} {...headerGroup.getHeaderGroupProps((column)=>({
+                style: {
+                  ...column.style,
+                  height: '40px',
+                }
+              }))}>
                 {headerGroup.headers.map((column) => (
                   <div
                     key={column.id}
@@ -472,14 +476,14 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
                     className={clsx(classes.tableCellHeader, column.className)}
                   >
                     <div
-                      {...(column.sortble ? column.getSortByToggleProps() : {})}
+                      {...(column.sortable ? column.getSortByToggleProps() : {})}
                     >
                       {column.render('Header')}
                       <span>
                         {column.isSorted
                           ? column.isSortedDesc
-                            ? ' 🔽'
-                            : ' 🔼'
+                            ? <KeyboardArrowDownIcon style={{fontSize: '1.2rem'}} />
+                            : <KeyboardArrowUpIcon style={{fontSize: '1.2rem'}} />
                           : ''}
                       </span>
                     </div>
@@ -507,14 +511,13 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
                       height={height}
                       itemCount={rows.length}
                       itemSize={getRowHeight}
-                      sorted={props?.sortOptions}
                     >
                       {RenderRow}
                     </VariableSizeList>)}
                 </AutoSizer>
               </div>
             ) : (
-              <EmptyPanelMessage text={gettext('No record found')}/>
+              <EmptyPanelMessage text={gettext('No rows found')}/>
             )
           }
         </div>
@@ -526,7 +529,7 @@ export default function PgTable({ columns, data, isSelectRow, caveTable=true, ..
 PgTable.propTypes = {
   stepId: PropTypes.number,
   height: PropTypes.number,
-  customHeader: PropTypes.func,
+  CustomHeader: PropTypes.func,
   className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
   caveTable: PropTypes.bool,
   fixedSizeList: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
@@ -544,8 +547,8 @@ PgTable.propTypes = {
   setSelectedRows: PropTypes.func,
   getSelectedRows: PropTypes.func,
   searchText: PropTypes.string,
-  type: PropTypes.string,
   sortOptions: PropTypes.array,
   schema: PropTypes.object,
-  rows: PropTypes.object
+  rows: PropTypes.object,
+  ExpandedComponent: PropTypes.node,
 };
diff --git a/web/pgadmin/static/js/custom_hooks.js b/web/pgadmin/static/js/custom_hooks.js
index a38088851..b77df8d70 100644
--- a/web/pgadmin/static/js/custom_hooks.js
+++ b/web/pgadmin/static/js/custom_hooks.js
@@ -13,6 +13,7 @@ export function useInterval(callback, delay) {
     }
 
     if(delay > -1) {
+      tick();
       let id = setInterval(tick, delay);
       return () => clearInterval(id);
     }
diff --git a/web/pgadmin/static/js/helpers/Notifier.jsx b/web/pgadmin/static/js/helpers/Notifier.jsx
index 95d837e8e..702c780ec 100644
--- a/web/pgadmin/static/js/helpers/Notifier.jsx
+++ b/web/pgadmin/static/js/helpers/Notifier.jsx
@@ -92,7 +92,7 @@ const useModalStyles = makeStyles((theme)=>({
   },
   margin: {
     marginLeft: '0.25rem',
-  }
+  },
 }));
 function AlertContent({text, confirm, okLabel=gettext('OK'), cancelLabel=gettext('Cancel'), onOkClick, onCancelClick}) {
   const classes = useModalStyles();
@@ -144,11 +144,10 @@ var Notifier = {
     }
   },
   _callNotify(msg, type, autoHideDuration) {
-    if (!_.isNull(autoHideDuration)) {
-      this.notify(<NotifierMessage type={type} message={msg} closable={false} />, autoHideDuration);
-    } else {
-      this.notify(<NotifierMessage type={type} message={msg}/>, null);
-    }
+    this.notify(
+      <NotifierMessage style={{maxWidth: '50vw'}} type={type} message={msg} closable={_.isNull(autoHideDuration) ? true : false} />,
+      autoHideDuration
+    );
   },
 
   pgRespErrorNotify(xhr, error, prefixMsg='') {
diff --git a/web/pgadmin/tools/backup/__init__.py b/web/pgadmin/tools/backup/__init__.py
index 0742e5882..afc6f00f8 100644
--- a/web/pgadmin/tools/backup/__init__.py
+++ b/web/pgadmin/tools/backup/__init__.py
@@ -6,7 +6,6 @@
 # This software is released under the PostgreSQL Licence
 #
 ##########################################################################
-
 """Implements Backup Utility"""
 
 import simplejson as json
@@ -161,8 +160,7 @@ class BackupMessage(IProcessDesc):
     def details(self, cmd, args):
         name, host, port = self.get_server_details()
 
-        res = '<div>'
-
+        msg = "Backup"
         if self.backup_type == BACKUP.OBJECT:
             msg = _(
                 "Backing up an object on the server '{0}' "
@@ -173,7 +171,6 @@ class BackupMessage(IProcessDesc):
                 ),
                 self.database
             )
-            res += html.safe_str(msg)
         elif self.backup_type == BACKUP.GLOBALS:
             msg = _("Backing up the global objects on "
                     "the server '{0}'...").format(
@@ -181,25 +178,17 @@ class BackupMessage(IProcessDesc):
                     name, host, port
                 )
             )
-            res += html.safe_str(msg)
         elif self.backup_type == BACKUP.SERVER:
             msg = _("Backing up the server '{0}'...").format(
                 self.args_str.format(
                     name, host, port
                 )
             )
-            res += html.safe_str(msg)
-        else:
-            # It should never reach here.
-            res += "Backup"
-
-        res += '</div><div class="py-1">'
-        res += _("Running command:")
-        res += '<div class="pg-bg-cmd enable-selection p-1">'
-        res += html.safe_str(cmd + self.cmd)
-        res += '</div></div>'
 
-        return res
+        return {
+            "message": msg,
+            "cmd": cmd + self.cmd
+        }
 
 
 @blueprint.route("/")
@@ -487,7 +476,7 @@ def create_backup_objects_job(sid):
 
     # Return response
     return make_json_response(
-        data={'job_id': jid, 'Success': 1}
+        data={'job_id': jid, 'desc': p.desc.message, 'Success': 1}
     )
 
 
diff --git a/web/pgadmin/tools/backup/static/js/backup.js b/web/pgadmin/tools/backup/static/js/backup.js
index afe0c50a9..ca2642fbe 100644
--- a/web/pgadmin/tools/backup/static/js/backup.js
+++ b/web/pgadmin/tools/backup/static/js/backup.js
@@ -181,7 +181,7 @@ define([
           gettext(data.errormsg)
         );
       } else {
-        pgBrowser.Events.trigger('pgadmin-bgprocess:created');
+        pgBrowser.BgProcessManager.startProcess(data.data.job_id, data.data.desc);
       }
     },
     url_for_utility_exists(id, params){
diff --git a/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx b/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx
index 2706432be..9fedec760 100644
--- a/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx
+++ b/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx
@@ -65,21 +65,21 @@ export default function GrantWizard({ sid, did, nodeInfo, nodeData, onClose }) {
 
       Header: 'Object Type',
       accessor: 'object_type',
-      sortble: true,
+      sortable: true,
       resizable: false,
       disableGlobalFilter: true
     },
     {
       Header: 'Schema',
       accessor: 'nspname',
-      sortble: true,
+      sortable: true,
       resizable: false,
       disableGlobalFilter: true
     },
     {
       Header: 'Name',
       accessor: 'name_with_args',
-      sortble: true,
+      sortable: true,
       resizable: true,
       disableGlobalFilter: false,
       minWidth: 280
@@ -87,7 +87,7 @@ export default function GrantWizard({ sid, did, nodeInfo, nodeData, onClose }) {
     {
       Header: 'parameters',
       accessor: 'proargs',
-      sortble: false,
+      sortable: false,
       resizable: false,
       disableGlobalFilter: false,
       minWidth: 280,
@@ -96,7 +96,7 @@ export default function GrantWizard({ sid, did, nodeInfo, nodeData, onClose }) {
     {
       Header: 'Name',
       accessor: 'name',
-      sortble: false,
+      sortable: false,
       resizable: false,
       disableGlobalFilter: false,
       minWidth: 280,
@@ -105,7 +105,7 @@ export default function GrantWizard({ sid, did, nodeInfo, nodeData, onClose }) {
     {
       Header: 'ID',
       accessor: 'oid',
-      sortble: false,
+      sortable: false,
       resizable: false,
       disableGlobalFilter: false,
       minWidth: 280,
diff --git a/web/pgadmin/tools/import_export/__init__.py b/web/pgadmin/tools/import_export/__init__.py
index f30229da9..1555b9779 100644
--- a/web/pgadmin/tools/import_export/__init__.py
+++ b/web/pgadmin/tools/import_export/__init__.py
@@ -123,28 +123,20 @@ class IEMessage(IProcessDesc):
         # Fetch the server details like hostname, port, roles etc
         name, host, port = self.get_server_details()
 
-        res = '<div>'
-        res += _(
+        msg = _(
             "Copying table data '{0}.{1}' on database '{2}' "
             "for the server '{3}'"
         ).format(
-            html.safe_str(self.schema),
-            html.safe_str(self.table),
-            html.safe_str(self.database),
-            "{0} ({1}:{2})".format(
-                html.safe_str(name),
-                html.safe_str(host),
-                html.safe_str(port)
-            )
+            self.schema,
+            self.table,
+            self.database,
+            "{0} ({1}:{2})".format(name, host, port)
         )
 
-        res += '</div><div class="py-1">'
-        res += _("Running command:")
-        res += '<div class="pg-bg-cmd enable-selection p-1">'
-        res += html.safe_str(self._cmd)
-        res += '</div></div>'
-
-        return res
+        return {
+            "message": msg,
+            "cmd": self._cmd
+        }
 
 
 @blueprint.route("/")
@@ -387,7 +379,7 @@ def create_import_export_job(sid):
 
     # Return response
     return make_json_response(
-        data={'job_id': jid, 'success': 1}
+        data={'job_id': jid, 'desc': p.desc.message, 'success': 1}
     )
 
 
diff --git a/web/pgadmin/tools/import_export/static/js/import_export.js b/web/pgadmin/tools/import_export/static/js/import_export.js
index 4cfebf480..14b787062 100644
--- a/web/pgadmin/tools/import_export/static/js/import_export.js
+++ b/web/pgadmin/tools/import_export/static/js/import_export.js
@@ -83,7 +83,7 @@ define([
         );
       } else {
         Notify.success(gettext('Import/Export job created.'));
-        pgBrowser.Events.trigger('pgadmin-bgprocess:created');
+        pgBrowser.BgProcessManager.startProcess(data.data.job_id, data.data.desc);
       }
     },
 
diff --git a/web/pgadmin/tools/maintenance/__init__.py b/web/pgadmin/tools/maintenance/__init__.py
index f84da2587..53ca712c0 100644
--- a/web/pgadmin/tools/maintenance/__init__.py
+++ b/web/pgadmin/tools/maintenance/__init__.py
@@ -129,15 +129,10 @@ class Message(IProcessDesc):
         return res
 
     def details(self, cmd, args):
-
-        res = '<div>' + self.message
-        res += '</div><div class="py-1">'
-        res += _("Running Query:")
-        res += '<div class="pg-bg-cmd enable-selection p-1">'
-        res += html.safe_str(self.query)
-        res += '</div></div>'
-
-        return res
+        return {
+            "message": self.message,
+            "query": self.query
+        }
 
 
 @blueprint.route("/")
@@ -272,7 +267,7 @@ def create_maintenance_job(sid, did):
 
     # Return response
     return make_json_response(
-        data={'job_id': jid, 'status': True,
+        data={'job_id': jid, 'desc': p.desc.message, 'status': True,
               'info': _('Maintenance job created.')}
     )
 
diff --git a/web/pgadmin/tools/maintenance/static/js/maintenance.js b/web/pgadmin/tools/maintenance/static/js/maintenance.js
index cbf9388e0..46a058196 100644
--- a/web/pgadmin/tools/maintenance/static/js/maintenance.js
+++ b/web/pgadmin/tools/maintenance/static/js/maintenance.js
@@ -93,7 +93,7 @@ define([
         );
       } else {
         Notify.success(data.data.info);
-        pgBrowser.Events.trigger('pgadmin-bgprocess:created');
+        pgBrowser.BgProcessManager.startProcess(data.data.job_id, data.data.desc);
       }
     },
     setExtraParameters(treeInfo) {
diff --git a/web/pgadmin/tools/restore/__init__.py b/web/pgadmin/tools/restore/__init__.py
index 76f4d9df3..dec38c7b8 100644
--- a/web/pgadmin/tools/restore/__init__.py
+++ b/web/pgadmin/tools/restore/__init__.py
@@ -107,22 +107,15 @@ class RestoreMessage(IProcessDesc):
 
     def details(self, cmd, args):
         name, host, port = self.get_server_details()
-        res = '<div>'
-
-        res += html.safe_str(
-            _(
-                "Restoring backup on the server '{0}'..."
-            ).format(
-                "{0} ({1}:{2})".format(name, host, port)
-            )
+        msg = _(
+            "Restoring backup on the server '{0}'..."
+        ).format(
+            "{0} ({1}:{2})".format(name, host, port)
         )
-
-        res += '</div><div class="py-1">'
-        res += _("Running command:")
-        res += '<div class="pg-bg-cmd enable-selection p-1">'
-        res += html.safe_str(cmd + self.cmd)
-        res += '</div></div>'
-        return res
+        return {
+            "message": msg,
+            "cmd": cmd + self.cmd
+        }
 
 
 @blueprint.route("/")
@@ -434,7 +427,7 @@ def create_restore_job(sid):
         )
     # Return response
     return make_json_response(
-        data={'job_id': jid, 'Success': 1}
+        data={'job_id': jid, 'desc': p.desc.message, 'Success': 1}
     )
 
 
diff --git a/web/pgadmin/tools/restore/static/js/restore.js b/web/pgadmin/tools/restore/static/js/restore.js
index 3ad192cf5..0f33ef334 100644
--- a/web/pgadmin/tools/restore/static/js/restore.js
+++ b/web/pgadmin/tools/restore/static/js/restore.js
@@ -97,7 +97,7 @@ define('tools.restore', [
           gettext(data.errormsg)
         );
       } else {
-        pgBrowser.Events.trigger('pgadmin-bgprocess:created');
+        pgBrowser.BgProcessManager.startProcess(data.data.job_id, data.data.desc);
       }
     },
     setExtraParameters: function(treeInfo, nodeData) {
diff --git a/web/regression/javascript/fake_endpoints.js b/web/regression/javascript/fake_endpoints.js
index 79686fe55..b06219974 100644
--- a/web/regression/javascript/fake_endpoints.js
+++ b/web/regression/javascript/fake_endpoints.js
@@ -36,5 +36,9 @@ define(function () {
     'file_manager.save_file_dialog_view': '/file_manager/save_file_dialog_view/<int:trans_id>',
     'file_manager.save_show_hidden_file_option': '/file_manager/save_show_hidden_file_option/<int:trans_id>',
     'settings.save_file_format_setting': '/settings/save_file_format_setting/',
+    'bgprocess.detailed_status': '/misc/bgprocess/<pid>/<int:out>/<int:err>/',
+    'bgprocess.list': '/misc/bgprocess/',
+    'bgprocess.stop_process': '/misc/bgprocess/stop/<pid>',
+    'bgprocess.acknowledge': '/misc/bgprocess/<pid>'
   };
 });
diff --git a/web/regression/javascript/processes/BgProcessManager.spec.js b/web/regression/javascript/processes/BgProcessManager.spec.js
new file mode 100644
index 000000000..573f88129
--- /dev/null
+++ b/web/regression/javascript/processes/BgProcessManager.spec.js
@@ -0,0 +1,120 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from 'axios/index';
+import BgProcessManager, { BgProcessManagerProcessState } from '../../../pgadmin/misc/bgprocess/static/js/BgProcessManager';
+import * as BgProcessNotify from '../../../pgadmin/misc/bgprocess/static/js/BgProcessNotify';
+
+
+
+describe('BgProcessManager', ()=>{
+  let obj;
+  let networkMock;
+  const pgBrowser = jasmine.createSpyObj('pgBrowser', [], {
+    docker: {
+      findPanels: ()=>{/* dummy */},
+      addPanel: ()=>{/* dummy */}
+    }
+  });
+
+  beforeAll(()=>{
+    networkMock = new MockAdapter(axios);
+    networkMock.onGet('/misc/bgprocess/').reply(200, [{}]);
+    networkMock.onPut('/misc/bgprocess/stop/12345').reply(200,{});
+    networkMock.onPut('/misc/bgprocess/12345').reply(200,{});
+  });
+
+  afterAll(() => {
+    networkMock.restore();
+  });
+
+  beforeEach(()=>{
+    obj = new BgProcessManager(pgBrowser);
+  });
+
+  it('init', ()=>{
+    spyOn(obj, 'startWorker');
+    obj.init();
+    expect(obj.startWorker).toHaveBeenCalled();
+  });
+
+  it('procList', ()=>{
+    obj._procList = [{a: '1'}];
+    expect(obj.procList).toEqual([{a: '1'}]);
+  });
+
+  it('startWorker', (done)=>{
+    spyOn(obj, 'syncProcesses');
+    obj._pendingJobId = ['123123123123'];
+    obj.startWorker();
+
+    setTimeout(()=>{
+      expect(obj.syncProcesses).toHaveBeenCalled();
+      done();
+    }, 2000);
+  });
+
+  it('startProcess', ()=>{
+    let nSpy = spyOn(BgProcessNotify, 'processStarted');
+    obj.startProcess('12345', 'process desc');
+    expect(obj._pendingJobId).toEqual(['12345']);
+    expect(nSpy.calls.mostRecent().args[0]).toBe('process desc');
+  });
+
+
+  it('stopProcess', (done)=>{
+    obj._procList = [{
+      id: '12345',
+      process_state: BgProcessManagerProcessState.PROCESS_STARTED,
+    }];
+
+    obj.stopProcess('12345');
+    setTimeout(()=>{
+      expect(obj._procList[0].process_state).toBe(BgProcessManagerProcessState.PROCESS_TERMINATED);
+      done();
+    }, 500);
+  });
+
+  it('acknowledge', (done)=>{
+    obj._procList = [{
+      id: '12345',
+      process_state: BgProcessManagerProcessState.PROCESS_FINISHED,
+    }];
+
+    obj.acknowledge('12345');
+    setTimeout(()=>{
+      expect(obj._procList.length).toBe(0);
+      done();
+    }, 500);
+  });
+
+
+  it('checkPending', ()=>{
+    obj._procList = [{
+      id: '12345',
+      process_state: BgProcessManagerProcessState.PROCESS_FINISHED,
+    }];
+    obj._pendingJobId = ['12345'];
+    let nSpy = spyOn(BgProcessNotify, 'processCompleted');
+    obj.checkPending();
+    expect(nSpy).toHaveBeenCalled();
+  });
+
+
+  it('openProcessesPanel', ()=>{
+    const panel = {
+      focus: ()=>{/* dummy */}
+    };
+    spyOn(pgBrowser.docker, 'addPanel').and.returnValue(panel);
+
+    /* panel open */
+    spyOn(pgBrowser.docker, 'findPanels').and.returnValue([panel]);
+    obj.openProcessesPanel();
+    expect(pgBrowser.docker.addPanel).not.toHaveBeenCalled();
+
+    /* panel closed */
+    spyOn(pgBrowser.docker, 'findPanels')
+      .withArgs('processes').and.returnValue([])
+      .withArgs('properties').and.returnValue([panel]);
+    obj.openProcessesPanel();
+    expect(pgBrowser.docker.addPanel).toHaveBeenCalled();
+  });
+});
diff --git a/web/regression/javascript/processes/BgProcessNotify.spec.js b/web/regression/javascript/processes/BgProcessNotify.spec.js
new file mode 100644
index 000000000..454d8ba2c
--- /dev/null
+++ b/web/regression/javascript/processes/BgProcessNotify.spec.js
@@ -0,0 +1,75 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import jasmineEnzyme from 'jasmine-enzyme';
+import '../helper/enzyme.helper';
+import { createMount } from '@material-ui/core/test-utils';
+import BgProcessManager, { BgProcessManagerProcessState } from '../../../pgadmin/misc/bgprocess/static/js/BgProcessManager';
+import pgAdmin from 'sources/pgadmin';
+import * as BgProcessNotify from '../../../pgadmin/misc/bgprocess/static/js/BgProcessNotify';
+import Notifier from '../../../pgadmin/static/js/helpers/Notifier';
+
+describe('BgProcessNotify', ()=>{
+  let mount;
+
+  /* Use createMount so that material ui components gets the required context */
+  /* https://material-ui.com/guides/testing/#api */
+  beforeAll(()=>{
+    mount = createMount();
+  });
+
+  afterAll(() => {
+    mount.cleanUp();
+  });
+
+  beforeEach(()=>{
+    jasmineEnzyme();
+    pgAdmin.Browser = pgAdmin.Browser || {};
+    pgAdmin.Browser.BgProcessManager = new BgProcessManager(pgAdmin.Browser);
+  });
+
+  it('processStarted', ()=>{
+    const nspy = spyOn(Notifier, 'notify');
+    BgProcessNotify.processStarted('some desc', ()=>{/* dummy */});
+    expect(nspy.calls.mostRecent().args[0].props).toEqual(jasmine.objectContaining({
+      title: 'Process started',
+      desc: 'some desc',
+    }));
+  });
+
+  it('processCompleted success', ()=>{
+    const nspy = spyOn(Notifier, 'notify');
+    BgProcessNotify.processCompleted('some desc', BgProcessManagerProcessState.PROCESS_FINISHED, ()=>{/* dummy */});
+    expect(nspy.calls.mostRecent().args[0].props).toEqual(jasmine.objectContaining({
+      title: 'Process completed',
+      desc: 'some desc',
+      success: true,
+    }));
+  });
+
+  it('processCompleted failed', ()=>{
+    const nspy = spyOn(Notifier, 'notify');
+    BgProcessNotify.processCompleted('some desc', BgProcessManagerProcessState.PROCESS_FAILED, ()=>{/* dummy */});
+    expect(nspy.calls.mostRecent().args[0].props).toEqual(jasmine.objectContaining({
+      title: 'Process failed',
+      desc: 'some desc',
+      success: false,
+    }));
+  });
+
+  it('processCompleted terminated', ()=>{
+    const nspy = spyOn(Notifier, 'notify');
+    BgProcessNotify.processCompleted('some desc', BgProcessManagerProcessState.PROCESS_TERMINATED, ()=>{/* dummy */});
+    expect(nspy.calls.mostRecent().args[0].props).toEqual(jasmine.objectContaining({
+      title: 'Process terminated',
+      desc: 'some desc',
+      success: false,
+    }));
+  });
+});
diff --git a/web/regression/javascript/processes/Proceses.spec.js b/web/regression/javascript/processes/Proceses.spec.js
new file mode 100644
index 000000000..0de21f8ca
--- /dev/null
+++ b/web/regression/javascript/processes/Proceses.spec.js
@@ -0,0 +1,76 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import jasmineEnzyme from 'jasmine-enzyme';
+import React from 'react';
+import '../helper/enzyme.helper';
+import { createMount } from '@material-ui/core/test-utils';
+import Theme from '../../../pgadmin/static/js/Theme';
+import BgProcessManager, { BgProcessManagerProcessState } from '../../../pgadmin/misc/bgprocess/static/js/BgProcessManager';
+import pgAdmin from 'sources/pgadmin';
+import Processes from '../../../pgadmin/misc/bgprocess/static/js/Processes';
+
+
+const processData = {
+  acknowledge: null,
+  current_storage_dir: null,
+  desc: 'Doing some operation on the server \'PostgreSQL 12 (localhost:5432)\'',
+  details: {
+    cmd: '/Library/PostgreSQL/12/bin/mybin --testing',
+    message: 'Doing some detailed operation on the server \'PostgreSQL 12 (localhost:5432)\'...'
+  },
+  etime: null,
+  execution_time: 0.09,
+  exit_code: null,
+  id: '220803091429498400',
+  process_state: BgProcessManagerProcessState.PROCESS_STARTED,
+  stime: '2022-08-03T09:14:30.191940+00:00',
+  type_desc: 'Operation on the server',
+  utility_pid: 140391
+};
+
+describe('Proceses', ()=>{
+  let mount;
+
+  /* Use createMount so that material ui components gets the required context */
+  /* https://material-ui.com/guides/testing/#api */
+  beforeAll(()=>{
+    mount = createMount();
+  });
+
+  afterAll(() => {
+    mount.cleanUp();
+  });
+
+  beforeEach(()=>{
+    jasmineEnzyme();
+    pgAdmin.Browser = pgAdmin.Browser || {};
+    pgAdmin.Browser.BgProcessManager = new BgProcessManager(pgAdmin.Browser);
+    pgAdmin.Browser.BgProcessManager._procList = [processData];
+  });
+
+  describe('ProcessDetails', ()=>{
+    let ctrlMount = (props)=>{
+      return mount(<Theme>
+        <Processes
+          {...props}
+        />
+      </Theme>);
+    };
+
+    it('init', (done)=>{
+      let ctrl = ctrlMount({});
+      setTimeout(()=>{
+        ctrl.update();
+        expect(ctrl.find('PgTable').length).toBe(1);
+        done();
+      }, 1000);
+    });
+  });
+});
diff --git a/web/regression/javascript/processes/ProcessDetails.spec.js b/web/regression/javascript/processes/ProcessDetails.spec.js
new file mode 100644
index 000000000..e9fd59745
--- /dev/null
+++ b/web/regression/javascript/processes/ProcessDetails.spec.js
@@ -0,0 +1,116 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import jasmineEnzyme from 'jasmine-enzyme';
+import React from 'react';
+import '../helper/enzyme.helper';
+import { createMount } from '@material-ui/core/test-utils';
+import Theme from '../../../pgadmin/static/js/Theme';
+import MockAdapter from 'axios-mock-adapter';
+import axios from 'axios/index';
+import ProcessDetails from '../../../pgadmin/misc/bgprocess/static/js/ProcessDetails';
+import BgProcessManager, { BgProcessManagerProcessState } from '../../../pgadmin/misc/bgprocess/static/js/BgProcessManager';
+import pgAdmin from 'sources/pgadmin';
+import { MESSAGE_TYPE } from '../../../pgadmin/static/js/components/FormComponents';
+import _ from 'lodash';
+
+
+const processData = {
+  acknowledge: null,
+  current_storage_dir: null,
+  desc: 'Doing some operation on the server \'PostgreSQL 12 (localhost:5432)\'',
+  details: {
+    cmd: '/Library/PostgreSQL/12/bin/mybin --testing',
+    message: 'Doing some detailed operation on the server \'PostgreSQL 12 (localhost:5432)\'...'
+  },
+  etime: null,
+  execution_time: 0.09,
+  exit_code: null,
+  id: '220803091429498400',
+  process_state: BgProcessManagerProcessState.PROCESS_STARTED,
+  stime: '2022-08-03T09:14:30.191940+00:00',
+  type_desc: 'Operation on the server',
+  utility_pid: 140391
+};
+
+const detailsResponse = {
+  err: {
+    done: true,
+    lines: [['220803091259931276', 'INFO: operation log err']],
+    pos: 123
+  },
+  execution_time: 1.27,
+  exit_code: 0,
+  out: {
+    done: true,
+    lines: [['220803091259931276', 'INFO: operation log out']],
+    pos: 123
+  },
+  start_time: '2022-08-03 09:12:59.774503 +0000'
+};
+
+describe('ProcessDetails', ()=>{
+  let mount;
+  let networkMock;
+
+  /* Use createMount so that material ui components gets the required context */
+  /* https://material-ui.com/guides/testing/#api */
+  beforeAll(()=>{
+    mount = createMount();
+    networkMock = new MockAdapter(axios);
+    let initialResp = _.cloneDeep(detailsResponse);
+    initialResp.err.done = false;
+    initialResp.out.done = false;
+    initialResp.exit_code = null;
+    networkMock.onGet(`/misc/bgprocess/${processData.id}/0/0/`).reply(200, initialResp);
+    networkMock.onGet(`/misc/bgprocess/${processData.id}/123/123/`).reply(200, detailsResponse);
+  });
+
+  afterAll(() => {
+    mount.cleanUp();
+    networkMock.restore();
+  });
+
+  beforeEach(()=>{
+    jasmineEnzyme();
+    pgAdmin.Browser = pgAdmin.Browser || {};
+    pgAdmin.Browser.BgProcessManager = new BgProcessManager(pgAdmin.Browser);
+  });
+
+  describe('ProcessDetails', ()=>{
+    let ctrlMount = (props)=>{
+      return mount(<Theme>
+        <ProcessDetails
+          data={processData}
+          {...props}
+        />
+      </Theme>);
+    };
+
+    it('running and success', (done)=>{
+      let ctrl = ctrlMount({});
+      setTimeout(()=>{
+        ctrl.update();
+        expect(ctrl.find('NotifierMessage').props()).toEqual(jasmine.objectContaining({
+          type: MESSAGE_TYPE.INFO,
+          message: 'Running...',
+        }));
+        setTimeout(()=>{
+          ctrl.update();
+          expect(ctrl.find('NotifierMessage').props()).toEqual(jasmine.objectContaining({
+            type: MESSAGE_TYPE.SUCCESS,
+            message: 'Successfully completed.',
+          }));
+          ctrl.unmount();
+          done();
+        }, 2000);
+      }, 500);
+    });
+  });
+});
diff --git a/web/webpack.config.js b/web/webpack.config.js
index 8873198a4..5c2e590a8 100644
--- a/web/webpack.config.js
+++ b/web/webpack.config.js
@@ -473,7 +473,7 @@ module.exports = [{
           imports: [
             'pure|pgadmin.browser.quick_search',
             'pure|pgadmin.tools.user_management',
-            'pure|pgadmin.browser.bgprocess',
+            'pure|pgadmin.browser.bgprocessmanager',
             'pure|pgadmin.node.server_group',
             'pure|pgadmin.node.server',
             'pure|pgadmin.node.database',
diff --git a/web/webpack.shim.js b/web/webpack.shim.js
index d901421e8..a0e9298de 100644
--- a/web/webpack.shim.js
+++ b/web/webpack.shim.js
@@ -179,7 +179,7 @@ var webpackShimConfig = {
     'pgadmin.about': path.join(__dirname, './pgadmin/about/static/js/about'),
     'pgadmin.authenticate.kerberos': path.join(__dirname, './pgadmin/authenticate/static/js/kerberos'),
     'pgadmin.browser': path.join(__dirname, './pgadmin/browser/static/js/browser'),
-    'pgadmin.browser.bgprocess': path.join(__dirname, './pgadmin/misc/bgprocess/static/js/bgprocess'),
+    'pgadmin.browser.bgprocessmanager': path.join(__dirname, './pgadmin/misc/bgprocess/static/js'),
     'pgadmin.browser.collection': path.join(__dirname, './pgadmin/browser/static/js/collection'),
     'pgadmin.browser.datamodel': path.join(__dirname, './pgadmin/browser/static/js/datamodel'),
     'pgadmin.browser.endpoints': '/browser/js/endpoints',
