diff --git a/docs/en_US/cloud_deployment.rst b/docs/en_US/cloud_deployment.rst
new file mode 100644
index 000000000..5a29a115a
--- /dev/null
+++ b/docs/en_US/cloud_deployment.rst
@@ -0,0 +1,87 @@
+.. _cloud_deployment:
+
+******************************
+`Cloud Deployment`:index:
+******************************
+
+Deploying PostgreSQL server in the Amazon AWS cloud from pgAdmin 4 can be done through this module.
+Currently RDS is the only option, in future more cloud options are coming.
+
+To launch the *Cloud Deployment...* tool, right click on the *Server Group* or *Server* of the tree control, and select
+*Deploy and Register a Cloud Instance* from the *Register* menu.
+
+.. image:: images/cloud_deployment_provider.png
+    :alt: Cloud Deployment Provider
+    :align: center
+
+Once you launch the tool, the Amazon RDS is already selected as this is the only option currently available.
+Click on the *Next* button to proceed further.
+
+.. image:: images/cloud_deployment_credentials.png
+    :alt: Cloud Deployment Provider
+    :align: center
+
+In the Credentials dialog, provide the region in which you want to deploy the instance along with
+*AWS access key* and *AWS secret access key*.
+Provide *AWS session token* only if your AWS session is temporary.
+
+To proceed further, click on the next button. Before going further, pgAdmin will validate your credentials.
+
+.. image:: images/cloud_deployment_instance.png
+    :alt: Cloud Deployment Provider
+    :align: center
+
+Use the fields from the Instance Specification tab to specify the Instance details.
+
+* Use the *Instance name* field to add an instance name for the PostgreSQL server; the name
+  specified will be displayed in the *Browser* tree control too.
+
+* Use the *Public IP* field to specify the IP Address range for permitting the inbound traffic.
+
+* Use the *Database version* field to specify the PostgreSQL version to deploy.
+
+* Use the *Instance class* field to allocate the computational, network, and memory capacity required by planned workload of this DB instance.
+
+* Use the *Instance type* field to select the instance type.
+
+* Use the *Storage type* field to select the instance storage type. Three options are available. General Purpose (SSD) storage, Provisioned IOPS (SSD) and Magnetic storage.
+
+* Use the *Allocated storage* field to specify the storage capacity in GiB.
+
+* Use the *Provisioned IOPS* in case of  Provisioned IOPS (SSD) storage type.
+
+.. image:: images/cloud_deployment_database.png
+    :alt: Cloud Deployment Provider
+    :align: center
+
+Use the fields from the Database Details tab to specify the Instance details.
+
+* Use the drop-down list box in the *Server group* field to select the parent
+  node for the server; the server will be displayed in the *Browser* tree
+  control within the specified group.
+
+* Use the *Database name* field to add the database name for the PostgreSQL server.
+
+* Use the *Username* field to specify the name of a role that will be used when
+  authenticating with the server.
+
+* Use the *Password* field to provide a password that will be supplied when
+  authenticating with the server.
+
+* Use the *Confirm password* field to repeat the password.
+
+* Enter the listener port number of the server host in the *Port* field.
+
+.. image:: images/cloud_deployment_review.png
+    :alt: Cloud Deployment Provider
+    :align: center
+
+At the end, review the Instance details that you provided. Click on Finish button to deploy the instance on Amazon RDS.
+
+.. image:: images/cloud_deployment_tree.png
+    :alt: Cloud Deployment Provider
+    :align: center
+
+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. The Server will be added to the tree with the cloud uploading icon.
+Once the deployment is done, the necessary server details will be updated.
\ No newline at end of file
diff --git a/docs/en_US/deployment.rst b/docs/en_US/deployment.rst
index 8652c1027..653bbb807 100644
--- a/docs/en_US/deployment.rst
+++ b/docs/en_US/deployment.rst
@@ -17,3 +17,4 @@ will provide detailed information about creating a custom deployment.
    desktop_deployment
    server_deployment
    container_deployment
+   cloud_deployment
diff --git a/docs/en_US/images/cloud_deployment_credentials.png b/docs/en_US/images/cloud_deployment_credentials.png
new file mode 100644
index 0000000000000000000000000000000000000000..24d2041efbad01d6aa567bf084b21a7467a2d6cb
GIT binary patch
diff --git a/docs/en_US/images/cloud_deployment_database.png b/docs/en_US/images/cloud_deployment_database.png
new file mode 100644
index 0000000000000000000000000000000000000000..65107f2bb915e0e7209f910fec3c7a60143f879d
GIT binary patch
diff --git a/docs/en_US/images/cloud_deployment_instance.png b/docs/en_US/images/cloud_deployment_instance.png
new file mode 100644
index 0000000000000000000000000000000000000000..9db903b0095376689b1b6ecdb0ad987aaf272566
GIT binary patch
diff --git a/docs/en_US/images/cloud_deployment_provider.png b/docs/en_US/images/cloud_deployment_provider.png
new file mode 100644
index 0000000000000000000000000000000000000000..a5338c6673f829bb60855167e7850e58077e3f58
GIT binary patch
diff --git a/docs/en_US/images/cloud_deployment_review.png b/docs/en_US/images/cloud_deployment_review.png
new file mode 100644
index 0000000000000000000000000000000000000000..fb5b30992c3507dde44a8c79c101a928c6fda3a3
GIT binary patch
diff --git a/docs/en_US/images/cloud_deployment_tree.png b/docs/en_US/images/cloud_deployment_tree.png
new file mode 100644
index 0000000000000000000000000000000000000000..a43dac7ec1b78258658c3014bb8885d36c92d7ba
GIT binary patch
diff --git a/requirements.txt b/requirements.txt
index e24158924..6b44e2a19 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -45,3 +45,5 @@ requests==2.25.*
 pyotp==2.*
 qrcode==7.*
 Pillow==8.3.*
+boto3==1.17.112
+botocore==1.20.112
\ No newline at end of file
diff --git a/web/migrations/versions/1586db67b98e_.py b/web/migrations/versions/1586db67b98e_.py
new file mode 100644
index 000000000..4b4414a49
--- /dev/null
+++ b/web/migrations/versions/1586db67b98e_.py
@@ -0,0 +1,38 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2021, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""Added server id for cloud deployment
+
+Revision ID: 1586db67b98e
+Revises: 15c88f765bc8
+Create Date: 2022-01-04 13:08:05.484598
+
+"""
+from pgadmin.model import db
+
+
+# revision identifiers, used by Alembic.
+revision = '1586db67b98e'
+down_revision = '15c88f765bc8'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    db.engine.execute(
+        'ALTER TABLE process ADD COLUMN server_id INTEGER DEFAULT 0'
+    )
+    db.engine.execute(
+        'ALTER TABLE server ADD COLUMN cloud_status INTEGER DEFAULT 0'
+    )
+
+
+def downgrade():
+    # pgAdmin only upgrades, downgrade not implemented.
+    pass
diff --git a/web/pgacloud/pgacloud.py b/web/pgacloud/pgacloud.py
new file mode 100755
index 000000000..45fd97d4b
--- /dev/null
+++ b/web/pgacloud/pgacloud.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import argparse
+import os
+
+
+def load_providers():
+    """ Loads all the providers """
+    providers = {}
+
+    path = os.path.dirname(os.path.realpath(__file__))
+    modules = os.listdir(path + '/providers')
+
+    for filename in modules:
+        filename = path + '/providers/' + filename
+
+        if os.path.isfile(filename):
+            basename = os.path.basename(filename)
+            base, extension = os.path.splitext(basename)
+
+            if extension == ".py" and not basename.startswith("_"):
+                module = __import__("providers." + basename[:-3],
+                                    fromlist=["providers"])
+                provider = module.load()
+                providers[basename[:-3]] = provider
+
+    return providers
+
+
+def get_args(providers):
+    """ Creates the parsers and returns the args """
+    # Create the top-level parser
+    parser = argparse.ArgumentParser(prog='pgacloud.py')
+    parser.add_argument('--debug', action=argparse.BooleanOptionalAction,
+                        default=False, help='send debug messages to stderr')
+
+    # Create the provider sub-parser
+    parsers = parser.add_subparsers(help='provider help', dest='provider')
+
+    # Load the provider parsers
+    for provider in providers:
+        providers[provider].init_args(parsers)
+
+    args = parser.parse_args()
+
+    return parser, args
+
+
+def execute_command(providers, parser, args):
+    """ Executes the command in the provider """
+
+    # Switch - for _ in command names. We use - in the CLI syntax for ease of
+    # use, but we need an _ in Python function names
+    if 'command' in args and args.command is not None:
+        args.command = args.command.replace('-', '_')
+
+    # Figure out what provider the command was for (if any) and call the
+    # relevant function. If we don't get a match, print the help
+    if args.provider in providers and \
+            'command' in args and \
+            args.command is not None:
+        command = providers[args.provider].commands()[args.command]
+        command(args)
+    else:
+        # If no provider has been given, display the top level help,
+        # otherwise, call the help() method in the provider
+        if args.provider is None:
+            parser.print_help()
+        else:
+            command = providers[args.provider].commands()['help']
+            command()
+
+
+def main():
+    """ Entry point """
+    # Load the providers
+    providers = load_providers()
+
+    # Get the args
+    parser, args = get_args(providers)
+
+    # Execute the command
+    execute_command(providers, parser, args)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/web/pgacloud/providers/__init__.py b/web/pgacloud/providers/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/web/pgacloud/providers/_abstract.py b/web/pgacloud/providers/_abstract.py
new file mode 100644
index 000000000..9547104eb
--- /dev/null
+++ b/web/pgacloud/providers/_abstract.py
@@ -0,0 +1,31 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+class AbsProvider:
+    """ Abstract provider """
+    parser = None
+
+    def init_args(self, parsers):
+        """Not Required."""
+        pass
+
+    def commands(self):
+        """ Get the list of commands for the current provider. """
+        attrs = filter(lambda attr: attr.startswith('cmd_'), dir(self))
+        commands = {}
+
+        for attr in attrs:
+            method = getattr(self, attr)
+            commands[attr[4:]] = method
+
+        return commands
+
+    def cmd_help(self):
+        """ Prints the provider level help """
+        self.parser.print_help()
diff --git a/web/pgacloud/providers/rds.py b/web/pgacloud/providers/rds.py
new file mode 100644
index 000000000..3d3093079
--- /dev/null
+++ b/web/pgacloud/providers/rds.py
@@ -0,0 +1,328 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+""" Amazon RDS PostgreSQL provider """
+
+import configparser
+import os
+import time
+import boto3
+
+from providers._abstract import AbsProvider
+from utils.io import debug, error, output
+from utils.misc import get_my_ip, get_random_id
+
+DEL_SEC_GROUP_MSG = 'Deleting security group: {}...'
+
+
+class RdsProvider(AbsProvider):
+    def __init__(self):
+        self._clients = {}
+
+        # Get the credentials; environment takes precedence over config
+        # TODO: Use the correct path on Windows
+        credentials = configparser.ConfigParser()
+        credentials.read('/Users/khushboovashi/.aws/credentials')
+
+        self._access_key = credentials.get('default', 'aws_access_key_id',
+                                           fallback='')
+        self._secret_key = credentials.get('default', 'aws_secret_access_key',
+                                           fallback='')
+        self._session_token = credentials.get('default', 'aws_session_token',
+                                              fallback='')
+        self._database_pass = None
+
+        if 'AWS_ACCESS_KEY_ID' in os.environ:
+            self._access_key = os.environ['AWS_ACCESS_KEY_ID']
+
+        if 'AWS_SECRET_ACCESS_KEY' in os.environ:
+            self._secret_key = os.environ['AWS_SECRET_ACCESS_KEY']
+
+        if 'AWS_SESSION_TOKEN' in os.environ:
+            self._session_token = os.environ['AWS_SESSION_TOKEN']
+
+        if 'AWS_DATABASE_PASSWORD' in os.environ:
+            self._database_pass = os.environ['AWS_DATABASE_PASSWORD']
+
+        # Get the default region
+        config = configparser.ConfigParser()
+        config.read('~/.aws/config')
+
+        self._default_region = config.get('default', 'region',
+                                          fallback='ap-southeast-1')
+
+    def init_args(self, parsers):
+        """ Create the command line parser for this provider """
+        self.parser = parsers.add_parser('rds',
+                                         help='Amazon AWS RDS PostgreSQL',
+                                         epilog='Credentials are read from '
+                                                '~/.aws/config by default and '
+                                                'can be overridden in the '
+                                                'AWS_ACCESS_KEY_ID and '
+                                                'AWS_SECRET_ACCESS_KEY '
+                                                'environment variables. '
+                                                'The default region is read '
+                                                'from ~/.aws/config and will '
+                                                'fall back to us-east-1 if '
+                                                'not present.')
+        self.parser.add_argument('--region', default=self._default_region,
+                                 help='name of the AWS region (default: {})'
+                                 .format(self._default_region))
+
+        # Create the command sub-parser
+        parsers = self.parser.add_subparsers(help='RDS commands',
+                                             dest='command')
+
+        # Create the create instance command parser
+        parser_create_instance = parsers.add_parser('create-instance',
+                                                    help='create a new '
+                                                         'instance')
+        parser_create_instance.add_argument('--name', required=True,
+                                            help='name of the instance')
+        parser_create_instance.add_argument('--db-name', default='postgres',
+                                            help='name of the default '
+                                                 'database '
+                                                 '(default: postgres)')
+        parser_create_instance.add_argument('--db-password', required=False,
+                                            help='password for the database')
+        parser_create_instance.add_argument('--db-username',
+                                            default='postgres',
+                                            help='user name for the database '
+                                                 '(default: postgres)')
+        parser_create_instance.add_argument('--db-port', type=int,
+                                            default=5432,
+                                            help='port of the database '
+                                                 '(default: 5432)')
+        parser_create_instance.add_argument('--db-version',
+                                            default='13.3',
+                                            help='version of PostgreSQL '
+                                                 'to deploy (default: 13.3)')
+        parser_create_instance.add_argument('--instance-type', required=True,
+                                            help='machine type for the '
+                                                 'instance nodes, e.g. '
+                                                 'db.m3.large')
+        parser_create_instance.add_argument('--storage-iops', type=int,
+                                            default=0,
+                                            help='storage IOPs to allocate '
+                                                 '(default: 0)')
+        parser_create_instance.add_argument('--storage-size', type=int,
+                                            required=True,
+                                            help='storage size in GB')
+        parser_create_instance.add_argument('--storage-type', default='gp2',
+                                            help='storage type for the data '
+                                                 'database (default: gp2)')
+        parser_create_instance.add_argument('--public-ip', default='127.0.0.1',
+                                            help='Public IP '
+                                                 '(default: 127.0.0.1)')
+
+        # Create the delete instance command parser
+        parser_delete_instance = parsers.add_parser('delete-instance',
+                                                    help='delete an instance')
+        parser_delete_instance.add_argument('--name', required=True,
+                                            help='name of the instance')
+        parser_delete_instance.add_argument('--security-group',
+                                            help='name of a security group to'
+                                                 'delete as well')
+
+    ##########################################################################
+    # AWS Helper functions
+    ##########################################################################
+    def _get_aws_client(self, type, args):
+        """ Create/cache/return an AWS client object """
+        if type in self._clients:
+            return self._clients[type]
+
+        session = boto3.Session(
+            aws_access_key_id=self._access_key,
+            aws_secret_access_key=self._secret_key
+        )
+
+        self._clients['type'] = session.client(type, region_name=args.region)
+
+        return self._clients['type']
+
+    def _create_security_group(self, args):
+        """ Create a new security group for the instance """
+        ec2 = self._get_aws_client('ec2', args)
+        ip = args.public_ip if args.public_ip else get_my_ip()
+
+        # Deploy the security group
+        try:
+            name = 'pgacloud_{}_{}_{}'.format(args.name,
+                                              ip.replace('.', '-'),
+                                              get_random_id())
+            debug(args, 'Creating security group: {}...'.format(name))
+            response = ec2.create_security_group(
+                Description='Inbound access for {} to RDS instance {}'.format(
+                    ip, args.name),
+                GroupName=name
+            )
+        except Exception as e:
+            error(args, str(e))
+
+        return response['GroupId']
+
+    def _add_ingress_rule(self, args, security_group):
+        """ Add a local -> PostgreSQL ingress rule to a security group """
+        ec2 = self._get_aws_client('ec2', args)
+        ip = args.public_ip if args.public_ip else '{}/32'.format(get_my_ip())
+        port = args.db_port or 5432
+
+        try:
+            debug(args,
+                  'Adding ingress rule for: {}...'.format(ip))
+            print("Started Adding Ingress Rules...")
+            ec2.authorize_security_group_ingress(
+                GroupId=security_group,
+                IpPermissions=[
+                    {
+                        'FromPort': port,
+                        'ToPort': port,
+                        'IpProtocol': 'tcp',
+                        'IpRanges': [
+                            {
+                                'CidrIp': ip,
+                                'Description': 'pgcloud client {}'.format(ip)
+                            },
+                        ]
+                    },
+                ]
+            )
+        except Exception as e:
+            error(args, e)
+
+    def _create_rds_instance(self, args, security_group):
+        """ Create an RDS instance """
+        ec2 = self._get_aws_client('ec2', args)
+        rds = self._get_aws_client('rds', args)
+
+        db_password = self._database_pass if self._database_pass is not None\
+            else args.db_password
+
+        try:
+            debug(args, 'Creating RDS instance: {}...'.format(args.name))
+            rds.create_db_instance(DBInstanceIdentifier=args.name,
+                                   AllocatedStorage=args.storage_size,
+                                   DBName=args.db_name,
+                                   Engine='postgres',
+                                   Port=args.db_port,
+                                   EngineVersion=args.db_version,
+                                   StorageType=args.storage_type,
+                                   StorageEncrypted=True,
+                                   Iops=args.storage_iops,
+                                   AutoMinorVersionUpgrade=True,
+                                   MultiAZ=False,
+                                   MasterUsername=args.db_username,
+                                   MasterUserPassword=db_password,
+                                   DBInstanceClass=args.instance_type,
+                                   VpcSecurityGroupIds=[
+                                       security_group,
+                                   ])
+
+        except rds.exceptions.DBInstanceAlreadyExistsFault as e:
+            try:
+                debug(args, DEL_SEC_GROUP_MSG.format(security_group))
+                ec2.delete_security_group(GroupId=security_group)
+            except Exception:
+                pass
+            error(args, 'RDS instance {} already exists.'.format(args.name))
+        except Exception as e:
+            try:
+                debug(args, DEL_SEC_GROUP_MSG.format(security_group))
+                ec2.delete_security_group(GroupId=security_group)
+            except Exception:
+                pass
+            error(args, e)
+
+        # Wait for completion
+        running = True
+        while running:
+            response = rds.describe_db_instances(
+                DBInstanceIdentifier=args.name)
+
+            db_instance = response['DBInstances'][0]
+            status = db_instance['DBInstanceStatus']
+
+            if status != 'creating' and status != 'backing-up':
+                running = False
+
+            if running:
+                time.sleep(5)
+
+        return response['DBInstances']
+
+    def _delete_rds_instance(self, args, name):
+        """ Delete an RDS instance """
+        rds = self._get_aws_client('rds', args)
+
+        debug(args, 'Deleting RDS instance: {}...'.format(name))
+        try:
+            rds.delete_db_instance(
+                DBInstanceIdentifier=name,
+                SkipFinalSnapshot=True,
+                DeleteAutomatedBackups=True
+            )
+        except Exception as e:
+            error(args, e)
+
+        # Wait for completion
+        while True:
+            try:
+                rds.describe_db_instances(DBInstanceIdentifier=args.name)
+            except rds.exceptions.DBInstanceNotFoundFault:
+                return
+            except Exception as e:
+                error(args, e)
+
+            time.sleep(5)
+
+    def _delete_security_group(self, args, id):
+        """ Delete a security group """
+        ec2 = self._get_aws_client('ec2', args)
+
+        debug(args, 'Deleting security group: {}...'.format(id))
+        try:
+            ec2.delete_security_group(
+                GroupId=id
+            )
+        except Exception as e:
+            error(args, e)
+
+    ##########################################################################
+    # User commands
+    ##########################################################################
+    def cmd_create_instance(self, args):
+        """ Create an RDS instance and security group """
+        security_group = self._create_security_group(args)
+        self._add_ingress_rule(args, security_group)
+        instance = self._create_rds_instance(args, security_group)
+
+        data = {'instance': {
+            'Id': instance[0]['DBInstanceIdentifier'],
+            'Location': instance[0]['AvailabilityZone'],
+            'SecurityGroupId': security_group,
+            'Hostname': instance[0]['Endpoint']['Address'],
+            'Port': instance[0]['Endpoint']['Port'],
+            'Database': instance[0]['DBName'],
+            'Username': instance[0]['MasterUsername']
+        }}
+
+        output(data)
+
+    def cmd_delete_instance(self, args):
+        """ Delete an RDS instance and (optionally) a security group """
+        self._delete_rds_instance(args, args.name)
+
+        if args.security_group is not None:
+            self._delete_security_group(args, args.security_group)
+
+
+def load():
+    """ Loads the current provider """
+    return RdsProvider()
diff --git a/web/pgacloud/utils/__init__.py b/web/pgacloud/utils/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/web/pgacloud/utils/io.py b/web/pgacloud/utils/io.py
new file mode 100644
index 000000000..510051791
--- /dev/null
+++ b/web/pgacloud/utils/io.py
@@ -0,0 +1,37 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import datetime
+import json
+import sys
+
+
+def debug(args, message):
+    """ Print a debug message """
+    if not args.debug:
+        return
+
+    now = datetime.datetime.now()
+
+    print('[{}]: {}'.format(now.strftime("%H:%M:%S"), message),
+          file=sys.stderr)
+
+
+def error(args, message):
+    """ Print an error message and exit """
+    debug(args, message)
+
+    output({'error': message})
+
+    sys.exit(1)
+
+
+def output(data):
+    """ Dump JSON output from a dict """
+    print(json.dumps(data))
diff --git a/web/pgacloud/utils/misc.py b/web/pgacloud/utils/misc.py
new file mode 100644
index 000000000..ef1b31159
--- /dev/null
+++ b/web/pgacloud/utils/misc.py
@@ -0,0 +1,33 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import random
+import string
+import urllib.request
+
+
+def get_my_ip():
+    """ Return the public IP of this host """
+    try:
+        external_ip = urllib.request.urlopen(
+            'https://ident.me').read().decode('utf8')
+    except Exception:
+        try:
+            external_ip = urllib.request.urlopen(
+                'https://ifconfig.me/ip').read().decode('utf8')
+        except Exception:
+            external_ip = '127.0.0.1'
+
+    return external_ip
+
+
+def get_random_id():
+    """ Return a random 10 byte string """
+    letters = string.ascii_letters + string.digits
+    return(''.join(random.choice(letters) for _ in range(10)))
diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py
index fbf094600..517232210 100644
--- a/web/pgadmin/browser/__init__.py
+++ b/web/pgadmin/browser/__init__.py
@@ -763,7 +763,7 @@ def index():
         mfa_enabled=is_mfa_enabled(),
         login_url=login_url,
         _=gettext,
-        auth_only_internal=auth_only_internal
+        auth_only_internal=auth_only_internal,
     ))
 
     # Set the language cookie after login, so next time the user will have that
diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py
index 392c81ae8..509f6cf92 100644
--- a/web/pgadmin/browser/server_groups/servers/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/__init__.py
@@ -112,6 +112,10 @@ def server_icon_and_background(is_connected, manager, server):
         return 'icon-shared-server-not-connected{0}'.format(
             server_background_color
         )
+    elif server.cloud_status == -1:
+        return 'icon-server-cloud-deploy{0}'.format(
+            server_background_color
+        )
     else:
         return 'icon-server-not-connected{0}'.format(
             server_background_color
@@ -256,7 +260,8 @@ class ServerModule(sg.ServerGroupPluginModule):
                 user_name=server.username,
                 shared=server.shared,
                 is_kerberos_conn=bool(server.kerberos_conn),
-                gss_authenticated=manager.gss_authenticated
+                gss_authenticated=manager.gss_authenticated,
+                cloud_status=server.cloud_status
             )
 
     @property
@@ -998,7 +1003,8 @@ class ServerNode(PGChildNodeView):
             'tunnel_authentication': tunnel_authentication,
             'kerberos_conn': bool(server.kerberos_conn),
             'gss_authenticated': manager.gss_authenticated,
-            'gss_encrypted': manager.gss_encrypted
+            'gss_encrypted': manager.gss_encrypted,
+            'cloud_status': server.cloud_status
         }
 
         return ajax_response(response)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
index 74d622c25..ee384f629 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
@@ -342,17 +342,17 @@ define('pgadmin.node.schema', [
         pgBrowser.add_menus([{
           name: 'create_schema_on_coll', node: 'coll-schema', module: this,
           applies: ['object', 'context'], callback: 'show_obj_properties',
-          category: 'create', priority: 4, label: gettext('Schema...'),
+          category: 'create', priority: 1, label: gettext('Schema...'),
           icon: 'wcTabIcon icon-schema', data: {action: 'create'},
         },{
           name: 'create_schema', node: 'schema', module: this,
           applies: ['object', 'context'], callback: 'show_obj_properties',
-          category: 'create', priority: 4, label: gettext('Schema...'),
+          category: 'create', priority: 1, label: gettext('Schema...'),
           icon: 'wcTabIcon icon-schema', data: {action: 'create'},
         },{
           name: 'create_schema', node: 'database', module: this,
           applies: ['object', 'context'], callback: 'show_obj_properties',
-          category: 'create', priority: 4, label: gettext('Schema...'),
+          category: 'create', priority: 1, label: gettext('Schema...'),
           icon: 'wcTabIcon icon-schema', data: {action: 'create'},
           enable: 'can_create_schema',
         },
diff --git a/web/pgadmin/browser/server_groups/servers/static/img/serverbeingdeployed.svg b/web/pgadmin/browser/server_groups/servers/static/img/serverbeingdeployed.svg
new file mode 100644
index 000000000..7b8382b7c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/static/img/serverbeingdeployed.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 25.4.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve">
+<g>
+	<path d="M29,12.3c0,0-5.6,0-10,4.4c-0.2,0.2-0.4,0.4-0.5,0.6c-0.8-0.1-2,0-2.6,0.6c-1.4,1.4-1.9,3.8-1.9,3.8l3.1-0.4v1.1l1.9,1.9
+		h1.1l-0.4,3.1c0,0,2.4-0.5,3.8-1.9c0.6-0.6,0.6-1.8,0.6-2.6c0.2-0.2,0.4-0.3,0.6-0.5C29,17.9,29,12.3,29,12.3z M22.8,17.3
+		c0-0.7,0.6-1.2,1.2-1.2s1.2,0.6,1.2,1.2s-0.6,1.2-1.2,1.2S22.8,18,22.8,17.3z"/>
+	<path d="M18,24.5c-0.6,0.6-1.5,0.3-1.5,0.3s-0.3-0.9,0.3-1.5c0,0,0.1-0.1,0.1-0.1l-0.3-0.3c-0.2,0.1-0.5,0.2-0.6,0.4
+		c-0.9,0.9-0.7,2.7-0.7,2.7s1.9,0.1,2.7-0.7c0.2-0.2,0.3-0.4,0.4-0.6l-0.3-0.3C18.1,24.4,18.1,24.5,18,24.5z"/>
+	<path d="M2.5,8.9h18.6c0.8,0,1.5-0.7,1.5-1.5V4.3c0-0.8-0.7-1.5-1.5-1.5H2.5C1.7,2.7,1,3.4,1,4.3v3.1C1,8.2,1.7,8.9,2.5,8.9z
+		 M18.8,4.6c0.6,0,1.2,0.5,1.2,1.2s-0.5,1.2-1.2,1.2s-1.2-0.5-1.2-1.2S18.2,4.6,18.8,4.6z M15.8,4.6c0.6,0,1.2,0.5,1.2,1.2
+		s-0.5,1.2-1.2,1.2s-1.2-0.5-1.2-1.2S15.1,4.6,15.8,4.6z"/>
+	<path d="M2.5,16.5h15.4c0.1-0.2,0.3-0.4,0.4-0.5c1.4-1.4,2.9-2.3,4.3-3v-1.1c0-0.8-0.7-1.5-1.5-1.5H2.5c-0.8,0-1.5,0.7-1.5,1.5V15
+		C1,15.8,1.7,16.5,2.5,16.5z M18.8,12.3c0.6,0,1.2,0.5,1.2,1.2c0,0.6-0.5,1.2-1.2,1.2s-1.2-0.5-1.2-1.2
+		C17.7,12.8,18.2,12.3,18.8,12.3z M15.8,12.3c0.6,0,1.2,0.5,1.2,1.2c0,0.6-0.5,1.2-1.2,1.2s-1.2-0.5-1.2-1.2
+		C14.6,12.8,15.1,12.3,15.8,12.3z"/>
+	<path d="M2.5,18.1c-0.8,0-1.5,0.7-1.5,1.5v3.1c0,0.8,0.7,1.5,1.5,1.5h10.1l0.7-3.2c0,0,0.3-1.6,1.2-2.9H2.5z"/>
+</g>
+</svg>
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/server.js b/web/pgadmin/browser/server_groups/servers/static/js/server.js
index 0793a52c1..af92c5602 100644
--- a/web/pgadmin/browser/server_groups/servers/static/js/server.js
+++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js
@@ -80,12 +80,12 @@ define('pgadmin.node.server', [
         pgBrowser.add_menus([{
           name: 'create_server_on_sg', node: 'server_group', module: this,
           applies: ['object', 'context'], callback: 'show_obj_properties',
-          category: 'create', priority: 1, label: gettext('Server...'),
+          category: 'register', priority: 1, label: gettext('Server...'),
           data: {action: 'create'}, icon: 'wcTabIcon icon-server', enable: 'canCreate',
         },{
           name: 'create_server', node: 'server', module: this,
           applies: ['object', 'context'], callback: 'show_obj_properties',
-          category: 'create', priority: 3, label: gettext('Server...'),
+          category: 'register', priority: 3, label: gettext('Server...'),
           data: {action: 'create'}, icon: 'wcTabIcon icon-server', enable: 'canCreate',
         },{
           name: 'connect_server', node: 'server', module: this,
@@ -814,8 +814,8 @@ define('pgadmin.node.server', [
       // Fetch the updated data
       $.get(server_url)
         .done(function(res) {
-          if (res.shared && _.isNull(res.username) && data.user_id != current_user.id){
-            if (!res.service){
+          if (res.shared && _.isNull(res.username) && data.user_id != current_user.id) {
+            if (!res.service) {
               pgAdmin.Browser.Node.callbacks.show_obj_properties.call(
                 pgAdmin.Browser.Nodes[tree.itemData(item)._type], {action: 'edit'}
               );
@@ -824,13 +824,31 @@ define('pgadmin.node.server', [
               tree.setInode(item);
               tree.addIcon(item, {icon: 'icon-shared-server-not-connected'});
               Notify.info('Please enter the server details to connect to the server. This server is a shared server.');
-            }else{
+            } else {
               data.is_connecting = false;
               tree.unload(item);
               tree.setInode(item);
               tree.addIcon(item, {icon: 'icon-shared-server-not-connected'});
             }
           }
+          else if (res.cloud_status == -1) {
+            $.ajax({
+              type: 'GET',
+              timeout: 30000,
+              url: url_for('cloud.update_cloud_process', {'sid': res.id}),
+              cache: false,
+              async: true,
+              contentType: 'application/json',
+            })
+              .done(function() {
+                pgAdmin.Browser.BackgroundProcessObsorver.update_process_list();
+              })
+              .fail(function() {
+                // FIXME:: What to do now?
+                console.warn(arguments);
+              });
+          }
+          return;
         }).always(function(){
           data.is_connecting = false;
         });
@@ -1039,7 +1057,7 @@ define('pgadmin.node.server', [
       };
 
       /* Wait till the existing request completes */
-      if(data.is_connecting) {
+      if(data.is_connecting || data.cloud_status == -1) {
         return;
       }
       data.is_connecting = true;
diff --git a/web/pgadmin/browser/server_groups/servers/templates/css/servers.css b/web/pgadmin/browser/server_groups/servers/templates/css/servers.css
index 829c273aa..54bc32722 100644
--- a/web/pgadmin/browser/server_groups/servers/templates/css/servers.css
+++ b/web/pgadmin/browser/server_groups/servers/templates/css/servers.css
@@ -33,3 +33,13 @@
   vertical-align: middle;
   height: 1.3em;
 }
+
+
+.icon-server-cloud-deploy {
+  background-image: url('{{ url_for('NODE-server.static', filename='img/serverbeingdeployed.svg') }}') !important;
+  background-repeat: no-repeat;
+  background-size: 20px !important;
+  align-content: center;
+  vertical-align: middle;
+  height: 1.3em;
+}
diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index 53c4ac45d..98a84df18 100644
--- a/web/pgadmin/browser/static/js/browser.js
+++ b/web/pgadmin/browser/static/js/browser.js
@@ -326,9 +326,18 @@ define('pgadmin.browser', [
     },
     menu_categories: {
       /* name, label (pair) */
+      'register': {
+        label: gettext('Register'),
+        priority: 1,
+        /* separator above this menu */
+        above: false,
+        below: true,
+        /* icon: 'fa fa-magic', */
+        single: true,
+      },
       'create': {
         label: gettext('Create'),
-        priority: 1,
+        priority: 2,
         /* separator above this menu */
         above: false,
         below: true,
diff --git a/web/pgadmin/browser/static/js/collection.js b/web/pgadmin/browser/static/js/collection.js
index 66151dddf..9f944ff19 100644
--- a/web/pgadmin/browser/static/js/collection.js
+++ b/web/pgadmin/browser/static/js/collection.js
@@ -46,7 +46,7 @@ define([
         pgAdmin.Browser.add_menus([{
           name: 'refresh', node: this.type, module: this,
           applies: ['object', 'context'], callback: 'refresh',
-          priority: 1, label: gettext('Refresh'),
+          priority: 2, label: gettext('Refresh'),
           icon: 'fa fa-sync-alt',
         }]);
 
diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js
index 0292ce335..8dc6a1a29 100644
--- a/web/pgadmin/browser/static/js/node.js
+++ b/web/pgadmin/browser/static/js/node.js
@@ -118,8 +118,8 @@ define('pgadmin.browser.node', [
         module: self,
         applies: ['object', 'context'],
         callback: 'refresh',
-        priority: 1,
-        label: gettext('Refresh'),
+        priority: 2,
+        label: gettext('Refresh...'),
         icon: 'fa fa-sync-alt',
       }]);
 
diff --git a/web/pgadmin/misc/bgprocess/__init__.py b/web/pgadmin/misc/bgprocess/__init__.py
index ab710b13e..e83b03503 100644
--- a/web/pgadmin/misc/bgprocess/__init__.py
+++ b/web/pgadmin/misc/bgprocess/__init__.py
@@ -14,7 +14,8 @@ the long running background-processes.
 from flask import url_for
 from flask_security import login_required
 from pgadmin.utils import PgAdminModule
-from pgadmin.utils.ajax import make_response, gone, success_return
+from pgadmin.utils.ajax import make_response, gone, success_return,\
+    make_json_response
 
 from .processes import BatchProcess
 
@@ -101,8 +102,25 @@ def acknowledge(pid):
         Positive status
     """
     try:
-        BatchProcess.acknowledge(pid)
-        return success_return()
+        process = BatchProcess(id=pid)
+        status, server = process.acknowledge(pid)
+        if status and len(server) > 0:
+            return make_json_response(
+                success=1,
+                data={'node': {
+                    'sid': server['id'],
+                    'gid': server['servergroup_id'],
+                    '_type': 'server',
+                    'icon': 'icon-server-not-connected',
+                    'id': 'server_{}'.format(server['id']),
+                    'label': server['name'],
+                    'status': server['status']
+                }}
+            )
+        elif status and len(server) == 0:
+            return success_return()
+        else:
+            return gone(errormsg=str(server))
     except LookupError as lerr:
         return gone(errormsg=str(lerr))
 
diff --git a/web/pgadmin/misc/bgprocess/process_executor.py b/web/pgadmin/misc/bgprocess/process_executor.py
index bdeffe34d..6273bf2e8 100755
--- a/web/pgadmin/misc/bgprocess/process_executor.py
+++ b/web/pgadmin/misc/bgprocess/process_executor.py
@@ -320,7 +320,13 @@ def execute(argv):
 
         kwargs = dict()
         kwargs['close_fds'] = False
-        kwargs['shell'] = True if _IS_WIN else False
+
+        tmp_argv_string = ' '.join(argv)
+        _is_cloud_deployment_process = True\
+            if tmp_argv_string.find('create-instance') >= 0 else False
+
+        kwargs['shell'] = True if _IS_WIN or _is_cloud_deployment_process\
+            else False
 
         # We need environment variables & values in string
         kwargs['env'] = os.environ.copy()
diff --git a/web/pgadmin/misc/bgprocess/processes.py b/web/pgadmin/misc/bgprocess/processes.py
index 5c5c2aa17..ffdc87283 100644
--- a/web/pgadmin/misc/bgprocess/processes.py
+++ b/web/pgadmin/misc/bgprocess/processes.py
@@ -20,6 +20,7 @@ from datetime import datetime
 from pickle import dumps, loads
 from subprocess import Popen, PIPE
 import logging
+import json
 
 from pgadmin.utils import u_encode, file_quote, fs_encoding, \
     get_complete_file_path, get_storage_directory, IS_WIN
@@ -482,6 +483,58 @@ class BatchProcess(object):
 
         return pos, completed
 
+    def _get_cloud_instance_details(self, j):
+        ctime = get_current_time(format='%y%m%d%H%M%S%f')
+        stdout = []
+        stderr = []
+        out = 0
+        err = 0
+        cloud_server_id = 0
+        cloud_process = 0
+        cloud_instance = ''
+
+        enc = sys.getdefaultencoding()
+        if enc == 'ascii':
+            enc = 'utf-8'
+        execution_time = None
+
+        if j is not None:
+            if self.stime is not None:
+                stime = parser.parse(j.start_time)
+                etime = parser.parse(j.end_time or get_current_time())
+
+                execution_time = BatchProcess.total_seconds(etime - stime)
+
+            out, out_completed = self.read_log(
+                self.stdout, stdout, out, ctime, j.exit_code, enc
+            )
+            err, err_completed = self.read_log(
+                self.stderr, stderr, err, ctime, j.exit_code, enc
+            )
+
+            if out_completed and not j.exit_code:
+                for value in stdout:
+                    if 'instance' in value[1]:
+                        cloud_instance = value[1]
+                        cloud_process = 1
+                        cloud_server_id = j.server_id
+
+                    if cloud_instance != '':
+                        cloud_instance = json.loads(cloud_instance)
+                    if type(cloud_instance) is dict and\
+                            'instance' in cloud_instance:
+                        from pgadmin.misc.cloud import update_server
+                        cloud_instance['instance']['sid'] = cloud_server_id
+                        cloud_instance['instance']['status'] = True
+                        return update_server(cloud_instance)
+            elif err_completed and j.exit_code > 0:
+                from pgadmin.misc.cloud import update_server
+                cloud_instance = {'instance': {}}
+                cloud_instance['instance']['sid'] = j.server_id
+                cloud_instance['instance']['status'] = False
+                return update_server(cloud_instance)
+            return False, None
+
     def status(self, out=0, err=0):
         ctime = get_current_time(format='%y%m%d%H%M%S%f')
 
@@ -544,8 +597,7 @@ class BatchProcess(object):
             },
             'start_time': self.stime,
             'exit_code': self.ecode,
-            'execution_time': execution_time,
-            'process_state': self.process_state
+            'execution_time': execution_time
         }
 
     @staticmethod
@@ -692,7 +744,8 @@ class BatchProcess(object):
                       "'{1}'").format(desc.sid, p.pid)
                 )
                 try:
-                    BatchProcess.acknowledge(p.pid)
+                    process = BatchProcess(id=p.pid)
+                    process.acknowledge(p.pid)
                 except LookupError as lerr:
                     current_app.logger.warning(
                         _("Status for the background process '{0}' could "
@@ -707,8 +760,7 @@ class BatchProcess(object):
     def total_seconds(dt):
         return round(dt.total_seconds(), 2)
 
-    @staticmethod
-    def acknowledge(_pid):
+    def acknowledge(self, _pid):
         """
         Acknowledge from the user, he/she has alredy watched the status.
 
@@ -716,6 +768,9 @@ class BatchProcess(object):
         And, delete the process information from the configuration, and the log
         files related to the process, if it has already been completed.
         """
+        status = True
+        _server = {}
+
         p = Process.query.filter_by(
             user_id=current_user.id, pid=_pid
         ).first()
@@ -724,15 +779,17 @@ class BatchProcess(object):
             raise LookupError(PROCESS_NOT_FOUND)
 
         if p.end_time is not None:
+            status, _server = self._get_cloud_instance_details(p)
             logdir = p.logdir
             db.session.delete(p)
             import shutil
             shutil.rmtree(logdir, True)
         else:
             p.acknowledge = get_current_time()
-
         db.session.commit()
 
+        return status, _server
+
     def set_env_variables(self, server, **kwargs):
         """Set environment variables"""
         if server:
@@ -776,3 +833,16 @@ class BatchProcess(object):
                     p.utility_pid)
             )
             current_app.logger.exception(e)
+
+    @staticmethod
+    def update_server_id(_pid, _sid):
+        p = Process.query.filter_by(
+            user_id=current_user.id, pid=_pid
+        ).first()
+
+        if p is None:
+            raise LookupError(PROCESS_NOT_FOUND)
+
+        # Update the cloud server id
+        p.server_id = _sid
+        db.session.commit()
diff --git a/web/pgadmin/misc/bgprocess/static/js/bgprocess.js b/web/pgadmin/misc/bgprocess/static/js/bgprocess.js
index 633354cf4..ca9924c66 100644
--- a/web/pgadmin/misc/bgprocess/static/js/bgprocess.js
+++ b/web/pgadmin/misc/bgprocess/static/js/bgprocess.js
@@ -96,8 +96,10 @@ define('misc.bgprocess', [
           pgBrowser.Events && pgBrowser.Events.on(
             'pgadmin-bgprocess:finished:' + this.id,
             function(process) {
-              if (!process.notifier)
+              if (!process.notifier) {
+                if (process.cloud_process == 1) process.update_cloud_server.apply(process);
                 process.show.apply(process);
+              }
             }
           );
         }
@@ -175,6 +177,12 @@ define('misc.bgprocess', [
           }
         }
 
+        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;
 
@@ -309,6 +317,46 @@ define('misc.bgprocess', [
           });
       },
 
+      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;
 
@@ -523,8 +571,24 @@ define('misc.bgprocess', [
           async: true,
           contentType: 'application/json',
         })
-          .done(function() {
-            return;
+          .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) _tree.addIcon(_item.domNode, {icon: _server.icon});
+                  else {
+                    _tree.remove(_item.domNode);
+                    _tree.refresh(_item.domNode.parent);
+                  }
+                }
+
+              }, 10);
+            } else return;
           })
           .fail(function() {
             console.warn(arguments);
@@ -595,7 +659,7 @@ define('misc.bgprocess', [
         var observer = this;
 
         $.ajax({
-          typs: 'GET',
+          type: 'GET',
           timeout: 30000,
           url: url_for('bgprocess.list'),
           cache: false,
diff --git a/web/pgadmin/misc/cloud/__init__.py b/web/pgadmin/misc/cloud/__init__.py
new file mode 100644
index 000000000..f6b11c0d8
--- /dev/null
+++ b/web/pgadmin/misc/cloud/__init__.py
@@ -0,0 +1,405 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2021, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""Implements Cloud Deployment"""
+
+import simplejson as json
+from flask import Response, url_for, session
+from flask import render_template, request, current_app
+from flask_babelex import gettext
+from flask_security import login_required, current_user
+
+from pgadmin.utils import PgAdminModule, html
+from pgadmin.utils.ajax import make_json_response,\
+    internal_server_error, bad_request, success_return
+
+from pgadmin.utils.constants import MIMETYPE_APP_JS
+from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
+from pgadmin.model import db, Server, Process
+from pgadmin.misc.cloud.utils.rds import RDS, verify_aws_credentials,\
+    get_aws_db_instances, get_aws_db_versions, clear_aws_session,\
+    get_aws_regions
+
+from config import root
+
+# set template path for sql scripts
+MODULE_NAME = 'cloud'
+server_info = {}
+
+
+class CloudModule(PgAdminModule):
+    """
+    class CloudModule(Object):
+
+        It is a wizard which inherits PgAdminModule
+        class and define methods to load its own
+        javascript file.
+
+    LABEL = gettext('Browser')
+    """
+
+    def get_own_stylesheets(self):
+        """
+        Returns:
+            list: the stylesheets used by this module.
+        """
+        stylesheets = []
+        return stylesheets
+
+    def get_own_javascripts(self):
+        """"
+        Returns:
+            list: js files used by this module
+        """
+        scripts = []
+        scripts.append({
+            'name': 'pgadmin.misc.cloud',
+            'path': url_for('cloud.index') + 'cloud',
+            'when': None
+        })
+        scripts.append({
+            'name': 'pgadmin.browser.wizard',
+            'path': url_for('browser.static', filename='js/wizard'),
+            'when': None
+        })
+        return scripts
+
+    def get_exposed_url_endpoints(self):
+        """
+        Returns:
+            list: URL endpoints for cloud module
+        """
+        return ['cloud.deploy_on_cloud',
+                'cloud.get_aws_db_versions',
+                'cloud.verify_credentials',
+                'cloud.get_aws_db_instances',
+                'cloud.update_cloud_server',
+                'cloud.update_cloud_process',
+                'cloud.get_aws_regions']
+
+
+# Create blueprint for CloudModule class
+blueprint = CloudModule(
+    MODULE_NAME, __name__, static_url_path='')
+
+
+@blueprint.route("/")
+@login_required
+def index():
+    return bad_request(
+        errormsg=gettext("This URL cannot be called directly.")
+    )
+
+
+@blueprint.route("/cloud.js")
+@login_required
+def script():
+    """render own javascript"""
+    res = Response(response=render_template(
+        "cloud/js/cloud.js", _=gettext),
+        status=200,
+        mimetype=MIMETYPE_APP_JS)
+    return res
+
+
+@blueprint.route('/cloud/verify_credentials/',
+                 methods=['POST'], endpoint='verify_credentials')
+@login_required
+def verify_credentials():
+    """Verify Credentials."""
+    data = json.loads(request.data, encoding='utf-8')
+
+    status, msg = verify_aws_credentials(data)
+    if status:
+        msg = 'verified'
+
+    return make_json_response(success=status, info=msg)
+
+
+@blueprint.route('/cloud/get_aws_db_instances/',
+                 methods=['GET'], endpoint='get_aws_db_instances')
+@login_required
+def get_db_instances():
+    """
+    Fetch AWS DB Instances based on engine version.
+    """
+    # Get Engine Version
+    eng_version = request.args.get('eng_version')
+    status, versions = get_aws_db_instances(eng_version)
+
+    if not status:
+        return make_json_response(
+            status=410,
+            success=0,
+            errormsg=versions
+        )
+
+    return make_json_response(data=versions)
+
+
+@blueprint.route('/cloud/get_aws_db_versions/',
+                 methods=['GET', 'POST'], endpoint='get_aws_db_versions')
+@login_required
+def get_db_versions():
+    """GET AWS Database Versions for AWS."""
+    status, versions = get_aws_db_versions()
+    if not status:
+        return make_json_response(
+            status=410,
+            success=0,
+            errormsg=str(versions)
+        )
+    return make_json_response(data=versions)
+
+
+@blueprint.route('/cloud/get_aws_regions/',
+                 methods=['GET', 'POST'], endpoint='get_aws_regions')
+@login_required
+def get_db_versions():
+    """GET AWS Regions for AWS."""
+    status, regions = get_aws_regions()
+    if not status:
+        return make_json_response(
+            status=410,
+            success=0,
+            errormsg=str(regions)
+        )
+    return make_json_response(data=regions)
+
+
+@blueprint.route(
+    '/cloud/deploy', methods=['POST'], endpoint='deploy_on_cloud'
+)
+@login_required
+def deploy_on_cloud():
+    """Deploy on Cloud"""
+
+    data = json.loads(request.data, encoding='utf-8')
+    from subprocess import Popen, PIPE
+    args = ['--debug',
+            data['cloud'],
+            '--region',
+            str(data['secret']['aws_region']),
+            'create-instance',
+            '--name',
+            data['instance_details']['aws_name'],
+            '--db-name',
+            data['db_details']['aws_db_name'],
+            '--db-username',
+            data['db_details']['aws_db_username'],
+            '--db-port',
+            data['db_details']['aws_db_port'],
+            '--db-version',
+            str(data['instance_details']['aws_db_version']),
+            '--instance-type',
+            data['instance_details']['aws_instance_type'],
+            '--storage-type',
+            data['instance_details']['aws_storage_type'],
+            '--storage-size',
+            str(data['instance_details']['aws_storage_size']),
+            '--public-ip',
+            str(data['instance_details']['aws_public_ip']),
+            ]
+
+    if data['instance_details']['aws_storage_type'] == 'io1':
+        args.append('--storage-iops')
+        args.append(str(data['instance_details']['aws_storage_IOPS']))
+
+    _cmd = 'python {0}/pgacloud/pgacloud.py {1}'.format(root, ' '.join(args))
+    try:
+        sid = _create_server({
+            'gid': data['db_details']['gid'],
+            'name': data['instance_details']['aws_name'],
+            'db': data['db_details']['aws_db_name'],
+            'username': data['db_details']['aws_db_username'],
+            'port': data['db_details']['aws_db_port'],
+            'cloud_status': -1
+        })
+
+        p = BatchProcess(
+            desc=CloudProcessDesc(sid, _cmd, data['cloud'],
+                                  data['instance_details']['aws_name']),
+            cmd=_cmd,
+            args=[]
+        )
+
+        env = dict()
+        env['AWS_ACCESS_KEY_ID'] = data['secret']['aws_access_key']
+        env['AWS_SECRET_ACCESS_KEY'] = data['secret']['aws_secret_access_key']
+
+        if 'aws_session_token' in data['secret'] and\
+                data['secret']['aws_session_token'] is not None:
+            env['AWS_SESSION_TOKEN'] = data['secret']['aws_session_token']
+
+        if 'aws_db_password' in data['db_details']:
+            env['AWS_DATABASE_PASSWORD'] = data[
+                'db_details']['aws_db_password']
+
+        p.set_env_variables(None, env=env)
+        p.update_server_id(p.id, sid)
+        p.start()
+
+    except Exception as e:
+        current_app.logger.exception(e)
+        return make_json_response(
+            status=410,
+            success=0,
+            errormsg=str(e)
+        )
+
+    # Return response
+    return make_json_response(
+        success=1,
+        data={'job_id': 1, 'node': {
+            '_id': sid,
+            '_pid': data['db_details']['gid'],
+            'connected': False,
+            '_type': 'server',
+            'icon': 'icon-server-cloud-deploy',
+            'id': 'server_{}'.format(sid),
+            'inode': True,
+            'label': data['instance_details']['aws_name'],
+            'server_type': 'pg',
+            'module': 'pgadmin.node.server',
+            'cloud_status': -1
+        }}
+    )
+
+
+def _create_server(data):
+    """Create Server"""
+    server = Server(
+        user_id=current_user.id,
+        servergroup_id=data.get('gid'),
+        name=data.get('name'),
+        maintenance_db=data.get('db'),
+        username=data.get('username'),
+        ssl_mode='prefer',
+        cloud_status=data.get('cloud_status')
+    )
+
+    db.session.add(server)
+    db.session.commit()
+
+    return server.id
+
+
+def update_server(data):
+    """Update Server."""
+    server_data = data
+    server = Server.query.filter_by(
+        user_id=current_user.id,
+        id=server_data['instance']['sid']
+    ).first()
+
+    if server is None:
+        return False, "Could not find the server."
+
+    if server_data['instance'] == '' or\
+            not server_data['instance']['status']:
+        db.session.delete(server)
+    else:
+        server.host = server_data['instance']['Hostname']
+        server.port = server_data['instance']['Port']
+        server.cloud_status = 1
+
+    try:
+        db.session.commit()
+    except Exception as e:
+        db.session.rollback()
+        return False, e.message
+
+    _server = {
+        'id': server.id,
+        'servergroup_id': server.servergroup_id,
+        'name': server.name
+    }
+    if not server_data['instance']['status']:
+        _server['status'] = False
+    else:
+        _server['status'] = True
+        clear_aws_session()
+
+    return True, _server
+
+
+@blueprint.route(
+    '/cloud/update_cloud_process/<sid>', methods=['GET'],
+    endpoint='update_cloud_process'
+)
+@login_required
+def update_cloud_process(sid):
+    """Update Cloud Server Process"""
+    _process = Process.query.filter_by(user_id=current_user.id,
+                                       server_id=sid).first()
+    _process.acknowledge = None
+    db.session.commit()
+    return success_return()
+
+
+@blueprint.route(
+    '/cloud/update_cloud_server', methods=['POST'],
+    endpoint='update_cloud_server'
+)
+@login_required
+def update_cloud_server():
+    """Update Cloud Server."""
+    server_data = json.loads(request.data, encoding='utf-8')
+    status, server = update_server(server_data)
+
+    if not status:
+        return make_json_response(
+            status=410, success=0, errormsg=server
+        )
+
+    return make_json_response(
+        success=1,
+        data={'node': {
+            'sid': server.id,
+            'gid': server.servergroup_id,
+            '_type': 'server',
+            'icon': 'icon-server-not-connected',
+            'id': 'server_{}'.format(server.id),
+            'label': server.name
+        }}
+    )
+
+
+class CloudProcessDesc(IProcessDesc):
+    """Cloud Server Process Description."""
+    def __init__(self, _sid, _cmd, _provider, _instance_name):
+        self.sid = _sid
+        self.cmd = _cmd
+        self.instance_name = _instance_name
+        self.provider = 'Amazon RDS'
+
+        if _provider == 'rds':
+            self.provider = 'Amazon RDS'
+        elif _provider == 'azure':
+            self.provider = 'Azure PostgreSQL'
+        else:
+            self.provider = 'EDB Big Animal'
+
+    @property
+    def message(self):
+        return "Deployment on {0} is started for instance {1}.".format(
+            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
+
+    @property
+    def type_desc(self):
+        return "Cloud Deployment"
diff --git a/web/pgadmin/misc/cloud/cloud_utils.py b/web/pgadmin/misc/cloud/cloud_utils.py
new file mode 100644
index 000000000..0a074ae40
--- /dev/null
+++ b/web/pgadmin/misc/cloud/cloud_utils.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2021, The pgAdmin Development Team
+# This software is released under the PostgreSQL License
+#
+##########################################################################
+
+def update_temp_server(self):
+    pass
diff --git a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
new file mode 100644
index 000000000..fe6ded224
--- /dev/null
+++ b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
@@ -0,0 +1,443 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import url_for from 'sources/url_for';
+import React from 'react';
+import { Box, Table, TableBody, TableCell, TableHead, TableRow, Paper } from '@material-ui/core';
+import { makeStyles } from '@material-ui/core/styles';
+import Wizard from '../../../../static/js/helpers/wizard/Wizard';
+import WizardStep from '../../../../static/js/helpers/wizard/WizardStep';
+import {FormFooterMessage, MESSAGE_TYPE, InputToggle } from '../../../../static/js/components/FormComponents';
+import getApiInstance from '../../../../static/js/api_instance';
+import SchemaView from '../../../../static/js/SchemaView';
+import Alertify from 'pgadmin.alertifyjs';
+import PropTypes from 'prop-types';
+import {CloudInstanceDetailsSchema, CloudDBCredSchema, DatabaseSchema} from './cloud_db_details_schema.ui';
+import { isEmptyString } from 'sources/validators';
+import pgAdmin from 'sources/pgadmin';
+import { getNodeAjaxOptions, getNodeListById } from 'pgbrowser/node_ajax';
+import { commonTableStyles } from '../../../../static/js/Theme';
+import clsx from 'clsx';
+
+
+const useStyles = makeStyles(() =>
+  ({
+    messageBox: {
+      marginBottom: '1em',
+      display: 'flex',
+    },
+    messagePadding: {
+      flex: 2.5
+    },
+    searchInput: {
+      flex: 1,
+      marginTop: 2,
+      borderLeft: 'none',
+      paddingLeft: 5
+    },
+    toggleButton: {
+      height: '100px',
+    },
+    table: {
+      marginLeft: '4px',
+      marginTop: '12px',
+    },
+    tableCellHeading: {
+      fontWeight: 'bold',
+      paddingLeft: '9px',
+    },
+    tableCell: {
+      padding: '9px',
+      paddingLeft: '11px',
+    }
+  }),
+);
+export default function CloudWizard({ nodeInfo, nodeData }) {
+  const classes = useStyles();
+  const tableClasses = commonTableStyles();
+
+  var steps = ['Cloud Provider', 'Credentials', 'Instance Specification', 'Database Details', 'Review'];
+  const [currentStep, setCurrentStep] = React.useState('');
+  const [selectionVal, setCloudSelection] = React.useState('');
+  const [errMsg, setErrMsg] = React.useState('');
+  const [CloudInstanceDetailsInstance, setCloudInstanceDetailsInstance] = React.useState();
+  const [cloudDBCredInstance, setCloudDBCredInstance] = React.useState();
+  const [cloudDBInstance, setCloudDBInstance] = React.useState();
+  const [cloudInstanceDetails, setCloudInstanceDetails] = React.useState({});
+  const [cloudDBCred, setCloudDBCred] = React.useState({});
+  const [cloudDBDetails, setCloudDBDetails] = React.useState({});
+  const [callRDSAPI, setCallRDSAPI] = React.useState({});
+  const axiosApi = getApiInstance();
+
+  React.useEffect(() => {
+    if (callRDSAPI == 2) {
+      const cloudDBInstanceSchema = new CloudInstanceDetailsSchema({
+        version: ()=>getNodeAjaxOptions('get_aws_db_versions', pgAdmin.Browser.Nodes['server'], nodeInfo, nodeData, {
+          useCache:false,
+          cacheNode: 'server',
+          customGenerateUrl: ()=>{
+            return url_for('cloud.get_aws_db_versions');
+          }
+        }),
+        getInstances: (engine, reload, options) =>
+        {
+          return new Promise((resolve, reject)=>{
+            const api = getApiInstance();
+            var _url = url_for('cloud.get_aws_db_instances') ;
+
+            if (engine) _url += '?eng_version=' + engine;
+            if (reload) {
+              api.get(_url)
+                .then(res=>{
+                  let data = res.data.data;
+                  resolve(data);
+                })
+                .catch((err)=>{
+                  reject(err);
+                });
+            } else {
+              resolve(options);
+            }
+          });
+        },
+        instance_type: ()=>getNodeAjaxOptions('get_aws_db_instances', pgAdmin.Browser.Nodes['server'], nodeInfo, nodeData, {
+          useCache:false,
+          cacheNode: 'server',
+          customGenerateUrl: ()=>{
+            return url_for('cloud.get_aws_db_instances');
+          }
+        }),
+        server_groups: ()=>getNodeListById(pgAdmin.Browser.Nodes['server_group'], nodeInfo, nodeData),
+      }, {
+        gid: nodeInfo['server_group']._id,
+      });
+      setCloudInstanceDetailsInstance(cloudDBInstanceSchema);
+    }
+  }, [callRDSAPI]);
+
+  React.useEffect(() => {
+    const cloudDBCredSchema = new CloudDBCredSchema({
+      regions: ()=>getNodeAjaxOptions('get_aws_regions', pgAdmin.Browser.Nodes['server'], nodeInfo, nodeData, {
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('cloud.get_aws_regions');
+        }
+      }),
+    });
+    setCloudDBCredInstance(cloudDBCredSchema);
+
+    const cloudDBSchema = new DatabaseSchema({
+      server_groups: ()=>getNodeListById(pgAdmin.Browser.Nodes['server_group'], nodeInfo, nodeData),
+    });
+    setCloudDBInstance(cloudDBSchema);
+
+  }, []);
+
+  const wizardStepChange = (data) => {
+    if (data.currentStep) {
+      setCurrentStep(data.currentStep);
+    } else {
+      setCurrentStep(0);
+    }
+  };
+
+  const onSave = () => {
+    var _url = url_for('cloud.deploy_on_cloud');
+    const post_data = {
+      gid: nodeInfo.server_group._id,
+      cloud: selectionVal,
+      secret: cloudDBCred,
+      instance_details:cloudInstanceDetails,
+      db_details: cloudDBDetails
+    };
+    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', Alertify.cloudWizardDialog());
+        Alertify.cloudWizardDialog().close();
+      })
+      .catch((error) => {
+        Alertify.error(gettext(`Error while saving cloud wizard data: ${error.response.data.errormsg}`));
+      });
+  };
+
+  const disableNextCheck = () => {
+    setCallRDSAPI(currentStep);
+    let isError = false;
+    switch (currentStep) {
+    case 0:
+      setCloudSelection('rds');
+      isError = false;
+      break;
+    case 1:
+      if (isEmptyString(cloudDBCred.aws_access_key) || isEmptyString(cloudDBCred.aws_secret_access_key)) {
+        isError = true;
+      }
+      break;
+    case 2:
+      if (isEmptyString(cloudInstanceDetails.aws_name) ||
+      isEmptyString(cloudInstanceDetails.aws_db_version) || isEmptyString(cloudInstanceDetails.aws_instance_type) ||
+      isEmptyString(cloudInstanceDetails.aws_storage_type) || isEmptyString(cloudInstanceDetails.aws_storage_size)) {
+        isError = true;
+      }
+
+      if(cloudInstanceDetails.aws_storage_type == 'io1' && isEmptyString(cloudInstanceDetails.aws_storage_IOPS)) {
+        isError = true;
+      }
+      break;
+    case 3:
+      if (isEmptyString(cloudDBDetails.aws_db_name) ||
+      isEmptyString(cloudDBDetails.aws_db_username) || isEmptyString(cloudDBDetails.aws_db_password)
+      ) {
+        isError = true;
+      }
+      break;
+    default:
+      isError = false;
+      break;
+    }
+    return isError;
+  };
+
+  const onBeforeNext = (activeStep) => {
+    return new Promise((resolve, reject)=>{
+      if(activeStep == 1) {
+        setErrMsg('Validating credentials...');
+        var _url = url_for('cloud.verify_credentials');
+        const post_data = {
+          cloud: selectionVal,
+          secret: cloudDBCred,
+        };
+        axiosApi.post(_url, post_data)
+          .then((res) => {
+            if(!res.data.success) {
+              setErrMsg(res.data.info);
+              reject();
+            } else {
+              setErrMsg('');
+              resolve();
+            }
+          })
+          .catch(() => {
+            setErrMsg('Error while checking cloud credentials');
+            reject();
+          });
+      } else {
+        resolve();
+      }
+    });
+  };
+
+  const onDialogHelp = () => {
+    window.open(url_for('help.static', { 'filename': 'cloud_deployment.html' }), 'pgadmin_help');
+  };
+
+  function createData(name, value) {
+    return { name, value };
+  }
+
+  let cloud = 'Amazon RDS';
+
+  switch (selectionVal) {
+  case 'rds':
+    cloud = 'Amazon RDS';
+    break;
+  case 'azure':
+    cloud = 'Azure PostgreSQL';
+    break;
+  case 'biganimal':
+    cloud = 'EDB Big Animal';
+    break;
+  }
+  const rows = [
+    createData('Cloud', cloud),
+    createData('Instance name', cloudInstanceDetails.aws_name),
+    createData('Public IP', cloudInstanceDetails.aws_public_ip),
+  ];
+
+  const rows1 = [
+    createData('Database name', cloudDBDetails.aws_db_name),
+    createData('Username', cloudDBDetails.aws_db_username),
+    createData('Password', 'xxxxxxx'),
+    createData('Port',  cloudDBDetails.aws_db_port),
+  ];
+
+  const rows2 = [
+    createData('PostgreSQL version', cloudInstanceDetails.aws_db_version),
+    createData('Instance type', cloudInstanceDetails.aws_instance_type),
+  ];
+
+  let _storage_type = 'General Purpose SSD (gp2)',
+    _io1 = undefined;
+
+  if(cloudInstanceDetails.aws_storage_type == 'gp2') _storage_type = 'General Purpose SSD (gp2)';
+  else if(cloudInstanceDetails.aws_storage_type == 'io1') {
+    _storage_type = 'Provisioned IOPS SSD (io1)';
+    _io1 = cloudInstanceDetails.aws_storage_IOPS;
+  }
+  else if(cloudInstanceDetails.aws_storage_type == 'magnetic') _storage_type = 'Magnetic';
+
+  const rows3 = [
+    createData('Storage type', _storage_type),
+    createData('Allocated storage', cloudInstanceDetails.aws_storage_size + ' GiB'),
+  ];
+  if (_io1 !== undefined) rows3.push(createData('Provisioned IOPS', _io1));
+
+  const onErrClose = React.useCallback(()=>{
+    setErrMsg('');
+  });
+
+  return (
+    <>
+      <Wizard
+        title={gettext('Deploy Cloud Instance')}
+        stepList={steps}
+        disableNextStep={disableNextCheck}
+        onStepChange={wizardStepChange}
+        onSave={onSave}
+        onHelp={onDialogHelp}
+        beforeNext={onBeforeNext}>
+        <WizardStep stepId={0}>
+          <Box className={classes.messageBox}>
+            <Box className={classes.messagePadding}>{gettext('Deploy on Amazon RDS cloud.')}</Box>
+          </Box>
+          <Box className={classes.messageBox}>
+            <InputToggle
+              value='rds'
+              options={[{'label': gettext('Amazon RDS'), value: 'rds'}]}
+              className={classes.toggleButton}
+              onChange={(value) => {
+                setCloudSelection(value);}
+              }
+            >
+            </InputToggle>
+          </Box>
+          <Box className={classes.messageBox}>
+            <Box className={classes.messagePadding}>{gettext('More cloud providers are coming soon...')}</Box>
+          </Box>
+        </WizardStep>
+        <WizardStep stepId={1} >
+          {cloudDBCredInstance &&
+            <SchemaView
+              formType={'dialog'}
+              getInitData={() => { }}
+              viewHelperProps={{ mode: 'create' }}
+              schema={cloudDBCredInstance}
+              showFooter={false}
+              isTabView={false}
+              onDataChange={(isChanged, changedData) => {
+                setCloudDBCred(changedData);
+              }}
+            />
+          }
+          <FormFooterMessage type={MESSAGE_TYPE.ERROR} message={errMsg} onClose={onErrClose} />
+        </WizardStep>
+        <WizardStep stepId={2} >
+          {CloudInstanceDetailsInstance &&
+            <SchemaView
+              formType={'dialog'}
+              getInitData={() => { }}
+              viewHelperProps={{ mode: 'create' }}
+              schema={CloudInstanceDetailsInstance}
+              showFooter={false}
+              isTabView={false}
+              onDataChange={(isChanged, changedData) => {
+                setCloudInstanceDetails(changedData);
+              }}
+            />
+          }
+        </WizardStep>
+        <WizardStep stepId={3} >
+          {cloudDBInstance &&
+            <SchemaView
+              formType={'dialog'}
+              getInitData={() => { }}
+              viewHelperProps={{ mode: 'create' }}
+              schema={cloudDBInstance}
+              showFooter={false}
+              isTabView={false}
+              onDataChange={(isChanged, changedData) => {
+                setCloudDBDetails(changedData);
+              }}
+            />
+          }
+        </WizardStep>
+        <WizardStep stepId={4} >
+          <Box className={classes.boxText}>{gettext('Please review the details before creating the cloud instance.')}</Box>
+          <Paper variant="outlined" elevation={0} className={classes.summaryContainer}>
+            <Table aria-label="simple table" className={clsx(tableClasses.table)}>
+              <TableBody>
+                {rows.map((row) => (
+                  <TableRow key={row.name} >
+                    <TableCell scope="row">{row.name}</TableCell>
+                    <TableCell align="right">{row.value}</TableCell>
+                  </TableRow>
+                ))}
+              </TableBody>
+            </Table>
+            <Table aria-label="simple table" className={clsx(tableClasses.table)}>
+              <TableHead>
+                <TableRow>
+                  <TableCell colSpan={2}>{gettext('Version and Instance Details')}</TableCell>
+                </TableRow>
+              </TableHead>
+              <TableBody>
+                {rows2.map((row) => (
+                  <TableRow key={row.name}>
+                    <TableCell scope="row">{row.name}</TableCell>
+                    <TableCell align="right">{row.value}</TableCell>
+                  </TableRow>
+                ))}
+              </TableBody>
+            </Table>
+            <Table aria-label="simple table" className={clsx(tableClasses.table)}>
+              <TableHead>
+                <TableRow>
+                  <TableCell colSpan={2}>{gettext('Storage Details')}</TableCell>
+                </TableRow>
+              </TableHead>
+              <TableBody>
+                {rows3.map((row) => (
+                  <TableRow key={row.name}>
+                    <TableCell scope="row">{row.name}</TableCell>
+                    <TableCell align="right">{row.value}</TableCell>
+                  </TableRow>
+                ))}
+              </TableBody>
+            </Table>
+            <Table aria-label="simple table" className={clsx(tableClasses.table)}>
+              <TableHead>
+                <TableRow>
+                  <TableCell colSpan={2}>{gettext('Database Details')}</TableCell>
+                </TableRow>
+              </TableHead>
+              <TableBody>
+                {rows1.map((row) => (
+                  <TableRow key={row.name} >
+                    <TableCell scope="row" >{row.name}</TableCell>
+                    <TableCell align="right">{row.value}</TableCell>
+                  </TableRow>
+                ))}
+              </TableBody>
+            </Table>
+          </Paper>
+        </WizardStep>
+      </Wizard>
+    </>
+  );
+}
+
+CloudWizard.propTypes = {
+  nodeInfo: PropTypes.object,
+  nodeData: PropTypes.object,
+};
+
+
diff --git a/web/pgadmin/misc/cloud/static/js/cloud.js b/web/pgadmin/misc/cloud/static/js/cloud.js
new file mode 100644
index 000000000..47eb28fe3
--- /dev/null
+++ b/web/pgadmin/misc/cloud/static/js/cloud.js
@@ -0,0 +1,151 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Theme from 'sources/Theme';
+import CloudWizard from './CloudWizard';
+
+
+// Grant Wizard
+define('pgadmin.misc.cloud', [
+  'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'backbone',
+  'pgadmin.alertifyjs', 'pgadmin.backgrid', 'pgadmin.backform',
+  'pgadmin.browser',
+  'pgadmin.browser.wizard',
+], function(
+  gettext, url_for, $, _, Backbone, Alertify, Backgrid, Backform, pgBrowser
+) {
+
+  // if module is already initialized, refer to that.
+  if (pgBrowser.Cloud) {
+    return pgBrowser.Cloud;
+  }
+
+
+  // Create an Object Cloud of pgBrowser class
+  pgBrowser.Cloud = {
+    init: function() {
+      if (this.initialized)
+        return;
+
+      this.initialized = true;
+
+      // Define the nodes on which the menus to be appear
+      var menus = [{
+        name: 'register_and_deploy_cloud_instance',
+        module: this,
+        applies: ['object', 'context'],
+        callback: 'start_cloud_wizard',
+        priority: 15,
+        label: gettext('Deploy and Register a Cloud Instance...'),
+        icon: 'wcTabIcon icon-server',
+        enable: true,
+        data: {action: 'create'},
+        category: 'register',
+        node: 'server_group',
+      }, {
+        name: 'register_and_deploy_cloud_instance',
+        module: this,
+        applies: ['object', 'context'],
+        callback: 'start_cloud_wizard',
+        priority: 15,
+        label: gettext('Deploy and Register a Cloud Instance...'),
+        icon: 'wcTabIcon icon-server',
+        enable: true,
+        data: {action: 'create'},
+        category: 'register',
+        node: 'server',
+      }];
+
+      pgBrowser.add_menus(menus);
+      return this;
+    },
+
+    // Callback to draw Wizard Dialog
+    start_cloud_wizard: function() {
+
+      // Declare Wizard dialog
+      if (!Alertify.cloudWizardDialog) {
+        Alertify.dialog('cloudWizardDialog', function factory() {
+
+          // Generate wizard main container
+          var $container = $('<div class=\'wizard_dlg\' id=\'cloudWizardDlg\'></div>');
+          return {
+            main: function () {
+            },
+            setup: function () {
+              return {
+                // Set options for dialog
+                options: {
+                  frameless: true,
+                  resizable: true,
+                  autoReset: false,
+                  maximizable: true,
+                  closable: true,
+                  closableByDimmer: false,
+                  modal: true,
+                  pinnable: false,
+                },
+              };
+            },
+            build: function () {
+              this.elements.content.appendChild($container.get(0));
+              Alertify.pgDialogBuild.apply(this);
+              var t = pgBrowser.tree,
+                i = t.selected(),
+                d = this.d = i ? t.itemData(i) : undefined,
+                info = this.info = pgBrowser.tree.getTreeNodeHierarchy(i);
+
+              setTimeout(function () {
+                if (document.getElementById('cloudWizardDlg')) {
+                  ReactDOM.render(
+                    <Theme>
+                      <CloudWizard nodeInfo={info} nodeData={d} />
+                    </Theme>,
+                    document.getElementById('cloudWizardDlg'));
+                  Alertify.cloudWizardDialog().elements.modal.style.maxHeight=0;
+                  Alertify.cloudWizardDialog().elements.modal.style.maxWidth='none';
+                  Alertify.cloudWizardDialog().elements.modal.style.overflow='visible';
+                  Alertify.cloudWizardDialog().elements.dimmer.style.display='none';
+                }
+              }, 500);
+
+            },
+            prepare: function () {
+              $container.empty().append('<div class=\'cloud_wizard_container\'></div>');
+            },
+            hooks: {
+              // Triggered when the dialog is closed
+              onclose: function () {
+                // Clear the view and remove the react component.
+                return setTimeout((function () {
+                  ReactDOM.unmountComponentAtNode(document.getElementById('cloudWizardDlg'));
+                  return Alertify.cloudWizardDialog().destroy();
+                }), 500);
+              },
+            }
+          };
+        });
+      }
+      // Call Grant Wizard Dialog and set dimensions for wizard
+      Alertify.cloudWizardDialog('').set({
+        onmaximize:function(){
+          Alertify.cloudWizardDialog().elements.modal.style.maxHeight='initial';
+        },
+        onrestore:function(){
+          Alertify.cloudWizardDialog().elements.modal.style.maxHeight=0;
+        },
+      }).resizeTo(920, 620);
+    },
+
+
+  };
+
+  return pgBrowser.Cloud;
+});
diff --git a/web/pgadmin/misc/cloud/static/js/cloud_db_details_schema.ui.js b/web/pgadmin/misc/cloud/static/js/cloud_db_details_schema.ui.js
new file mode 100644
index 000000000..a72b34c63
--- /dev/null
+++ b/web/pgadmin/misc/cloud/static/js/cloud_db_details_schema.ui.js
@@ -0,0 +1,291 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import { isEmptyString } from 'sources/validators';
+
+
+class CloudInstanceDetailsSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues) {
+    super({
+      oid: undefined,
+      aws_name: '',
+      aws_public_ip: '',
+      ...initValues
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+    this.initValues = initValues;
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [
+      {
+        id: 'aws_name', label: gettext('Instance name'), type: 'text',
+        mode: ['create'], noEmpty: true,
+      }, {
+        id: 'aws_public_ip', label: gettext('Public IP range'), type: 'text',
+        mode: ['create'],
+        helpMessage: gettext('IP Address range for permitting the inbound traffic. Ex: 127.0.0.1/32'),
+      }, {
+        type: 'nested-fieldset', label: gettext('Version & Instance'),
+        mode: ['create'],
+        schema: new InstanceSchema(this.fieldOptions.version,
+          this.fieldOptions.instance_type,
+          this.fieldOptions.getInstances),
+      }, {
+        type: 'nested-fieldset', label: gettext('Storage'),
+        mode: ['create'],
+        schema: new StorageSchema(),
+      },
+    ];
+  }
+}
+
+
+class CloudDBCredSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues) {
+    super({
+      oid: null,
+      aws_region: '',
+      aws_access_key: '',
+      aws_secret_access_key: '',
+      aws_session_token: '',
+      is_valid_cred: false,
+      ...initValues
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [
+      {
+        id: 'aws_region', label: gettext('Default region'),
+        type: 'select',
+        options: this.fieldOptions.regions,
+        controlProps: { allowClear: false },
+        noEmpty: true,
+      },{
+        id: 'aws_access_key', label: gettext('AWS access key'), type: 'text',
+        mode: ['create'], noEmpty: true,
+      }, {
+        id: 'aws_secret_access_key', label: gettext('AWS secret access Key'), type: 'text',
+        mode: ['create'], noEmpty: true,
+      }, {
+        id: 'aws_session_token', label: gettext('AWS session token'), type: 'multiline',
+        mode: ['create'], noEmpty: false,
+        helpMessage: gettext('Temporary AWS session required session token.')
+      }
+    ];
+  }
+}
+
+
+class DatabaseSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues={}) {
+    super({
+      oid: undefined,
+      gid: undefined,
+      aws_db_name: '',
+      aws_db_username: '',
+      aws_db_password: '',
+      aws_db_confirm_password: '',
+      aws_db_port: 5432,
+      ...initValues,
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+
+  }
+
+  validate(data, setErrMsg) {
+    if(!isEmptyString(data.aws_db_password) && !isEmptyString(data.aws_db_confirm_password)
+    && data.aws_db_password != data.aws_db_confirm_password) {
+      setErrMsg('aws_db_confirm_password', gettext('Passwords do not match.'));
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [{
+      id: 'gid', label: gettext('Server group'), type: 'select',
+      options: this.fieldOptions.server_groups,
+      mode: ['create'],
+      controlProps: { allowClear: false },
+      noEmpty: true,
+    }, {
+      id: 'aws_db_name', label: gettext('Database name'), type: 'text',
+      mode: ['create'], noEmpty: true,
+    }, {
+      id: 'aws_db_username', label: gettext('Username'), type: 'text',
+      mode: ['create'], noEmpty: true,
+    }, {
+      id: 'aws_db_password', label: gettext('Password'), type: 'password',
+      mode: ['create'], noEmpty: true,
+    }, {
+      id: 'aws_db_confirm_password', label: gettext('Confirm password'),
+      type: 'password',
+      mode: ['create'], noEmpty: true,
+    }, {
+      id: 'aws_db_port', label: gettext('Port'), type: 'text',
+      mode: ['create'], noEmpty: true,
+    }];
+  }
+}
+
+export class InstanceSchema extends BaseUISchema {
+  constructor(versionOpts, instanceOpts, getInstances) {
+    super({
+      aws_db_version: '',
+      aws_db_instance_class: 'm',
+      aws_instance_type: '',
+      reload_instances: true,
+    });
+    this.versionOpts = versionOpts;
+    this.instanceOpts = instanceOpts;
+    this.getInstances = getInstances;
+    this.instanceData = [];
+  }
+
+  get baseFields() {
+    return [{
+      id: 'aws_db_version', label: gettext('Database version'),
+      type: 'select',
+      options: this.versionOpts,
+      controlProps: { allowClear: false },
+      deps: ['aws_name'],
+      noEmpty: true,
+    },{
+      id: 'aws_db_instance_class', label: gettext('Instance class'),
+      type: 'toggle',
+      options: [
+        {'label': gettext('Standard classes (includes m classes)'), value: 'm'},
+        {'label': gettext('Memory optimized classes (includes r & x classes)'), value: 'x'},
+        {'label': gettext('Burstable classes (includes t classes)'), value: 't'},
+      ],  noEmpty: true, orientation: 'vertical',
+    },{
+      id: 'aws_instance_type', label: gettext('Instance type'),
+      options: this.instanceOpts,  noEmpty: true,
+      controlProps: { allowClear: false },
+      deps: ['aws_db_version', 'aws_db_instance_class'],
+      depChange: (state, source)=> {
+        if (source[0] == 'aws_db_instance_class') {
+          state.reload_instances = false;
+        } else {
+          state.reload_instances = true;
+        }
+      },
+      type: (state) => {
+        return {
+          type: 'select',
+          options: ()=>this.getInstances(state.aws_db_version,
+            state.reload_instances, state.instanceData),
+          optionsLoaded: (options) => { state.instanceData = options; },
+          optionsReloadBasis: state.aws_db_version + state.aws_db_instance_class,
+          controlProps: {
+            allowClear: false,
+            filter: (options) => {
+              let pattern = 'db.m';
+              let pattern_1 = 'db.m';
+
+              if (state.aws_db_instance_class) {
+                pattern = 'db.' + state.aws_db_instance_class;
+                pattern_1 = 'db.' + state.aws_db_instance_class;
+              }
+              if (state.aws_db_instance_class == 'x') {
+                pattern_1 = 'db.' + 'r';
+              }
+              return options.filter((option) => {
+                return (option.value.includes(pattern) || option.value.includes(pattern_1));
+              });
+            },
+          }
+        };
+      },
+    }];
+  }
+}
+
+
+export class StorageSchema extends BaseUISchema {
+  constructor() {
+    super({
+      aws_storage_type: 'io1',
+      aws_storage_size: 100,
+      aws_storage_IOPS: 3000,
+      aws_storage_msg: 'Minimum: 20 GiB. Maximum: 16,384 GiB.'
+    });
+  }
+
+  get baseFields() {
+    return [
+      {
+        id: 'aws_storage_type', label: gettext('Storage type'), type: 'select',
+        mode: ['create'],
+        options: [
+          {'label': gettext('General Purpose SSD (gp2)'), 'value': 'gp2'},
+          {'label': gettext('Provisioned IOPS SSD (io1)'), 'value': 'io1'},
+          {'label': gettext('Magnetic'), 'value': 'standard'}
+        ], noEmpty: true,
+      },{
+        id: 'aws_storage_size', label: gettext('Allocated storage'), type: 'text',
+        mode: ['create'], noEmpty: true, deps: ['aws_storage_type'],
+        depChange: (state)=> {
+          if(state.aws_storage_type === 'io1') {
+            state.aws_storage_size = 100;
+          } else if(state.aws_storage_type === 'gp2') {
+            state.aws_storage_size = 20;
+          } else {
+            state.aws_storage_size = 5;
+          }
+        },
+        helpMessage: gettext('Size in GiB.')
+      }, {
+        id: 'aws_storage_IOPS', label: gettext('Provisioned IOPS'), type: 'text',
+        mode: ['create'],
+        visible: (state) => {
+          if(state.aws_storage_type === 'io1') {
+            state.aws_storage_IOPS = 3000;
+            return true;
+          }
+          return false;
+        } , deps: ['aws_storage_type']
+      },
+    ];
+  }
+}
+
+export {
+  CloudInstanceDetailsSchema,
+  CloudDBCredSchema,
+  DatabaseSchema,
+};
diff --git a/web/pgadmin/misc/cloud/static/scss/_cloud.scss b/web/pgadmin/misc/cloud/static/scss/_cloud.scss
new file mode 100644
index 000000000..eec3c8d35
--- /dev/null
+++ b/web/pgadmin/misc/cloud/static/scss/_cloud.scss
@@ -0,0 +1,146 @@
+  /** Grant Wizard CSS **/
+
+/**
+  CSS to make db object type table
+  fixed so that tbody content may
+  scroll
+ */
+
+.db_objects_container  {
+  height: 100%;
+  padding: 0;
+}
+
+.db_objects_grid {
+  height: calc(100% - 15px);
+}
+
+.db_objects_filter {
+  & .input-group-text {
+    background: $input-bg;
+  }
+
+  & .form-control {
+    border-left: none;
+  }
+}
+
+.object_type_table {
+  height: calc(100% - 15px);
+  display: block;
+  padding: 0;
+  overflow-y: hidden !important;
+}
+
+.object_type_table thead {
+  display: table;
+  width: 100%;
+}
+
+.object_type_table thead tr {
+  position: relative;
+  display: block;
+  width: 100%;
+  border-bottom: $panel-border;
+}
+
+.object_type_table tbody {
+  display: block;
+  overflow: auto;
+  width: 100%;
+  /* 100% minus thead height */
+  height: calc(100% - 40px);
+}
+
+.object_type_table tbody tr {
+  max-width: 100%;
+  width: 100%;
+}
+
+.object_type_table tbody tr td {
+  background-position: 4px 4px;
+  border-radius: 0;
+}
+
+.object_type_table tbody tr td:nth-child(1),
+.object_type_table thead tr th:nth-child(1) {
+  width: 28px;
+  min-width: 28px;
+}
+
+.object_type_table tbody tr td:nth-child(2) {
+  width: 161px;
+  min-width: 161px;
+  max-width: 161px;
+}
+
+.object_type_table thead tr th:nth-child(2) {
+  width: 161px;
+  min-width: 161px;
+  max-width: 161px;
+}
+
+.object_type_table tbody tr td:nth-child(3) {
+  width: 109px;
+  min-width: 109px;
+  max-width: 109px;
+}
+
+.object_type_table thead tr th:nth-child(3) {
+  width: 109px;
+  min-width: 109px;
+  max-width: 109px;
+}
+
+.object_type_table thead tr th:nth-child(4) {
+  width: 100%;
+}
+
+.object_type_table tbody tr td:nth-child(4) {
+  width: 100%;
+  max-width: 100%;
+}
+
+/** Override Backgrid filter CSS **/
+.db_objects_container .backgrid-filter.form-search {
+  margin: 0px 5px 5px 0;
+}
+
+/** Custom styling for Codemirror field **/
+.wizard-right-panel_content {
+  border: 1px $color-gray-light;
+  padding: 0.5rem 0rem;
+  height: calc(100% - #{$footer-height-calc});
+}
+
+.wizard-right-panel_content .CodeMirror {
+  border: 1px solid $color-gray-light;
+  height: 100% !important;
+  min-height: 100% !important;
+}
+
+.wizard-right-panel_content .CodeMirror-linenumber {
+  background: $color-gray-light;
+  border-right: none;
+}
+
+.grant_wizard_container {
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+  height: 100%;
+}
+
+#grantWizardDlg {
+  padding-top: 0em;
+
+}
+
+.grant-wizard-objcol {
+  min-width: 8em !important;
+  width: 8em !important;
+}
+
+.grant-wizard-panel-content {
+  padding-top: 0.9em !important;
+}
diff --git a/web/pgadmin/misc/cloud/utils/rds.py b/web/pgadmin/misc/cloud/utils/rds.py
new file mode 100644
index 000000000..00589b1e4
--- /dev/null
+++ b/web/pgadmin/misc/cloud/utils/rds.py
@@ -0,0 +1,155 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2021, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+# AWS RDS PostgreSQL provider
+
+import boto3
+import pickle
+from flask import session
+
+
+class RDS():
+    def __init__(self, access_key, secret_key, session_token=None,
+                 default_region='ap-south-1'):
+        self._clients = {}
+
+        self._access_key = access_key
+        self._secret_key = secret_key
+        self._session_token = session_token
+
+        self._default_region = default_region
+
+    ##########################################################################
+    # AWS Helper functions
+    ##########################################################################
+    def _get_aws_client(self, type):
+        """ Create/cache/return an AWS client object """
+        if type in self._clients:
+            return self._clients[type]
+
+        session = boto3.Session(
+            aws_access_key_id=self._access_key,
+            aws_secret_access_key=self._secret_key,
+            aws_session_token=self._session_token
+        )
+
+        self._clients['type'] = session.client(
+            type, region_name=self._default_region)
+
+        return self._clients['type']
+
+    def get_available_db_version(self, engine='postgres'):
+        rds = self._get_aws_client('rds')
+        return rds.describe_db_engine_versions(Engine=engine)
+
+    def get_available_db_instance_class(self, engine='postgres',
+                                        engine_version='9.6'):
+        rds = self._get_aws_client('rds')
+        return rds.describe_orderable_db_instance_options(
+            Engine=engine,
+            EngineVersion=engine_version)
+
+    def get_db_instance(self, instance_name):
+        rds = self._get_aws_client('rds')
+        return rds.describe_db_instances(
+            DBInstanceIdentifier=instance_name)
+
+    def get_all_regions(self):
+        rds = self._get_aws_client('ec2')
+        return rds.describe_regions()
+
+    def validate_credentials(self):
+        client = self._get_aws_client('sts')
+        try:
+            identity = client.get_caller_identity()
+            return True, identity
+        except Exception as e:
+            return False, str(e)
+
+
+def verify_aws_credentials(data):
+    """Verify Credentials"""
+    session_token = data['secret']['aws_session_token'] if\
+        'aws_session_token' in data['secret'] else None
+
+    if 'aws' not in session:
+        session['aws'] = {}
+
+    if 'aws_rds_obj' not in session['aws'] or\
+            session['aws']['secret'] != data['secret']:
+        rds = RDS(
+            access_key=data['secret']['aws_access_key'],
+            secret_key=data['secret']['aws_secret_access_key'],
+            session_token=session_token,
+            default_region=data['secret']['aws_region'])
+        session['aws']['secret'] = data['secret']
+        session['aws']['aws_rds_obj'] = pickle.dumps(rds, -1)
+
+        return rds.validate_credentials()
+    return True, None
+
+
+def clear_aws_session():
+    """Clear AWS Session"""
+    if 'aws' in session:
+        session.pop('aws')
+
+
+def get_aws_db_instances(eng_version):
+    """Get AWS DB Instances"""
+    if 'aws' not in session:
+        return False, 'Session has not created yet.'
+
+    if not eng_version or eng_version == '' or eng_version == 'undefined':
+        eng_version = '9.6.1'
+
+    rds_obj = pickle.loads(session['aws']['aws_rds_obj'])
+    db_versions = rds_obj.get_available_db_instance_class(
+        engine_version=eng_version)
+    res = db_versions['OrderableDBInstanceOptions']
+    versions = []
+    for value in res:
+        versions.append({
+            'label': value['DBInstanceClass'],
+            'value': value['DBInstanceClass']
+        })
+    return True, versions
+
+
+def get_aws_db_versions():
+    """Get AWS DB Versions"""
+
+    if 'aws' not in session:
+        return False, 'Session has not created yet.'
+
+    rds_obj = pickle.loads(session['aws']['aws_rds_obj'])
+    db_versions = rds_obj.get_available_db_version()
+    res = db_versions['DBEngineVersions']
+    versions = []
+    for value in res:
+        versions.append({
+            'label': value['DBEngineVersionDescription'],
+            'value': value['EngineVersion']
+        })
+    return True, versions
+
+
+def get_aws_regions():
+    """Get AWS DB Versions"""
+
+    client = boto3.client('ec2')
+    db_versions = client.describe_regions()
+    res = db_versions['Regions']
+    regions = []
+    for value in res:
+        regions.append({
+            'label': value['RegionName'],
+            'value': value['RegionName']
+        })
+    return True, regions
diff --git a/web/pgadmin/model/__init__.py b/web/pgadmin/model/__init__.py
index 38a88992c..e4ce3ec30 100644
--- a/web/pgadmin/model/__init__.py
+++ b/web/pgadmin/model/__init__.py
@@ -30,7 +30,7 @@ import uuid
 #
 ##########################################################################
 
-SCHEMA_VERSION = 32
+SCHEMA_VERSION = 33
 
 ##########################################################################
 #
@@ -192,6 +192,7 @@ class Server(db.Model):
     tunnel_password = db.Column(db.String(64), nullable=True)
     shared = db.Column(db.Boolean(), nullable=False)
     kerberos_conn = db.Column(db.Boolean(), nullable=False, default=0)
+    cloud_status = db.Column(db.Integer(), nullable=False, default=0)
 
     @property
     def serialize(self):
@@ -325,6 +326,11 @@ class Process(db.Model):
     acknowledge = db.Column(db.String(), nullable=True)
     utility_pid = db.Column(db.Integer, nullable=False)
     process_state = db.Column(db.Integer, nullable=False)
+    server_id = db.Column(
+        db.Integer,
+        db.ForeignKey('server.id'),
+        nullable=True
+    )
 
 
 class Keys(db.Model):
diff --git a/web/pgadmin/static/js/SchemaView/MappedControl.jsx b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
index 243fff561..1d33798f4 100644
--- a/web/pgadmin/static/js/SchemaView/MappedControl.jsx
+++ b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
@@ -167,7 +167,8 @@ MappedCellControlBase.propTypes = {
 const ALLOWED_PROPS_FIELD_COMMON = [
   'mode', 'value', 'readonly', 'disabled', 'hasError', 'id',
   'label', 'options', 'optionsLoaded', 'controlProps', 'schema', 'inputRef',
-  'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis'
+  'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis',
+  'orientation'
 ];
 
 const ALLOWED_PROPS_FIELD_FORM = [
diff --git a/web/pgadmin/static/js/Theme/index.jsx b/web/pgadmin/static/js/Theme/index.jsx
index 265690ab4..f526a6071 100644
--- a/web/pgadmin/static/js/Theme/index.jsx
+++ b/web/pgadmin/static/js/Theme/index.jsx
@@ -417,6 +417,10 @@ function getFinalTheme(baseTheme) {
               backgroundColor: 'abc',
             }
           }
+        },
+
+        label: {
+          textTransform: 'initial',
         }
       },
       MuiFormHelperText: {
diff --git a/web/pgadmin/tools/backup/static/js/backup.js b/web/pgadmin/tools/backup/static/js/backup.js
index 7f9d28b74..373e92429 100644
--- a/web/pgadmin/tools/backup/static/js/backup.js
+++ b/web/pgadmin/tools/backup/static/js/backup.js
@@ -60,7 +60,7 @@ define([
         module: this,
         applies: ['tools'],
         callback: 'startBackupGlobal',
-        priority: 2,
+        priority: 3,
         label: gettext('Backup Globals...'),
         icon: 'fa fa-save',
         enable: menuUtils.menuEnabledServer,
@@ -72,7 +72,7 @@ define([
         module: this,
         applies: ['tools'],
         callback: 'startBackupServer',
-        priority: 2,
+        priority: 3,
         label: gettext('Backup Server...'),
         icon: 'fa fa-save',
         enable: menuUtils.menuEnabledServer,
@@ -85,7 +85,7 @@ define([
         node: 'server',
         applies: ['context'],
         callback: 'startBackupGlobal',
-        priority: 2,
+        priority: 3,
         label: gettext('Backup Globals...'),
         icon: 'fa fa-save',
         enable: menuUtils.menuEnabledServer,
@@ -98,7 +98,7 @@ define([
         node: 'server',
         applies: ['context'],
         callback: 'startBackupServer',
-        priority: 2,
+        priority: 3,
         label: gettext('Backup Server...'),
         icon: 'fa fa-save',
         enable: menuUtils.menuEnabledServer,
@@ -110,7 +110,7 @@ define([
         module: this,
         applies: ['tools'],
         callback: 'backupObjects',
-        priority: 2,
+        priority: 3,
         label: gettext('Backup...'),
         icon: 'fa fa-save',
         enable: supportedNodes.enabled.bind(
@@ -128,7 +128,7 @@ define([
           module: this,
           applies: ['context'],
           callback: 'backupObjects',
-          priority: 2,
+          priority: 3,
           label: gettext('Backup...'),
           icon: 'fa fa-save',
           enable: supportedNodes.enabled.bind(
diff --git a/web/webpack.config.js b/web/webpack.config.js
index 3181ecfe3..52fd8e087 100644
--- a/web/webpack.config.js
+++ b/web/webpack.config.js
@@ -549,6 +549,7 @@ module.exports = [{
             'pure|pgadmin.tools.search_objects',
             'pure|pgadmin.tools.erd_module',
             'pure|pgadmin.tools.psql_module',
+            'pure|pgadmin.misc.cloud',
           ],
         },
       },
diff --git a/web/webpack.shim.js b/web/webpack.shim.js
index 0430047c0..aad5bd183 100644
--- a/web/webpack.shim.js
+++ b/web/webpack.shim.js
@@ -220,6 +220,7 @@ var webpackShimConfig = {
     'pgadmin.file_utility': path.join(__dirname, './pgadmin/misc/file_manager/static/js/utility'),
     'pgadmin.help': path.join(__dirname, './pgadmin/help/static/js/help'),
     'pgadmin.misc.explain': path.join(__dirname, './pgadmin/misc/static/explain/js/explain'),
+    'pgadmin.misc.cloud': path.join(__dirname, './pgadmin/misc/cloud/static/js/cloud'),
     'pgadmin.node.cast': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/casts/static/js/cast'),
     'pgadmin.node.publication': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/publications/static/js/publication'),
     'pgadmin.node.subscription': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription'),
