diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py
index 44d55da8..ba3b7ee8 100644
--- a/web/pgadmin/tools/debugger/__init__.py
+++ b/web/pgadmin/tools/debugger/__init__.py
@@ -33,10 +33,10 @@ from pgadmin.settings import get_setting
 
 from config import PG_DEFAULT_DRIVER
 from pgadmin.model import db, DebuggerFunctionArguments
+from pgadmin.tools.debugger.utils.debugger_instance import DebuggerInstance
 
 # Constants
 ASYNC_OK = 1
-debugger_close_session_lock = Lock()
 
 
 class DebuggerModule(PgAdminModule):
@@ -234,14 +234,7 @@ class DebuggerModule(PgAdminModule):
         :param user:
         :return:
         """
-        with debugger_close_session_lock:
-            if 'debuggerData' in session:
-                for trans_id in session['debuggerData']:
-                    close_debugger_session(trans_id)
-
-                # Delete the all debugger data from session variable
-                del session['debuggerData']
-                del session['functionData']
+        close_debugger_session(None, close_all=True)
 
 
 blueprint = DebuggerModule(MODULE_NAME, __name__)
@@ -291,26 +284,6 @@ def script_debugger_direct_js():
     )
 
 
-def update_session_debugger_transaction(trans_id, data):
-    """
-    Update the session variables required for debugger with transaction ID
-    """
-    debugger_data = session['debuggerData']
-    debugger_data[str(trans_id)] = data
-
-    session['debuggerData'] = debugger_data
-
-
-def update_session_function_transaction(trans_id, data):
-    """
-    Update the session variables of functions required to debug with
-    transaction ID
-    """
-    function_data = session['functionData']
-    function_data[str(trans_id)] = data
-    session['functionData'] = function_data
-
-
 @blueprint.route(
     '/init/<node_type>/<int:sid>/<int:did>/<int:scid>/<int:fid>',
     methods=['GET'], endpoint='init_for_function'
@@ -404,10 +377,19 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
 
     # Check that the function is actually debuggable...
     if r_set['rows'][0]:
+        # If func/proc is not defined in package body
+        # then it is not debuggable
+        if (r_set['rows'][0]['pkgname'] is not None or
+            r_set['rows'][0]['pkgname'] != '') and \
+                r_set['rows'][0]['prosrc'] == '':
+            ret_status = False
+            msg = r_set['rows'][0]['name'] + ' ' + \
+                gettext("is not defined in package body.")
+
         # Function with a colon in the name cannot be debugged.
         # If this is an EDB wrapped function, no debugging allowed
         # Function with return type "trigger" cannot be debugged.
-        if ":" in r_set['rows'][0]['name']:
+        elif ":" in r_set['rows'][0]['name']:
             ret_status = False
             msg = gettext(
                 "Functions with a colon in the name cannot be debugged.")
@@ -469,12 +451,6 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
         current_app.logger.debug(msg)
         return internal_server_error(msg)
 
-    # Store the function information in session variable
-    if 'funcData' not in session:
-        function_data = dict()
-    else:
-        function_data = session['funcData']
-
     data = {'name': r_set['rows'][0]['proargnames'],
             'type': r_set['rows'][0]['proargtypenames'],
             'use_default': r_set['rows'][0]['pronargdefaults'],
@@ -502,7 +478,9 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
 
     r_set['rows'][0]['require_input'] = data['require_input']
 
-    function_data = {
+    # Create a debugger instance
+    de_inst = DebuggerInstance()
+    de_inst.function_data = {
         'oid': fid,
         'name': r_set['rows'][0]['name'],
         'is_func': r_set['rows'][0]['isfunc'],
@@ -522,10 +500,11 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
         'args_value': ''
     }
 
-    session['funcData'] = function_data
-
     return make_json_response(
-        data=r_set['rows'],
+        data=dict(
+            debug_info=r_set['rows'],
+            trans_id=de_inst.trans_id
+        ),
         status=200
     )
 
@@ -533,16 +512,15 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
 @blueprint.route('/direct/<int:trans_id>', methods=['GET'], endpoint='direct')
 @login_required
 def direct_new(trans_id):
-    debugger_data = session['debuggerData']
+    de_inst = DebuggerInstance(trans_id)
+
     # Return from the function if transaction id not found
-    if str(trans_id) not in debugger_data:
+    if de_inst.debugger_data is None:
         return make_json_response(data={'status': True})
 
-    obj = debugger_data[str(trans_id)]
-
     # if indirect debugging pass value 0 to client and for direct debugging
     # pass it to 1
-    debug_type = 0 if obj['debug_type'] == 'indirect' else 1
+    debug_type = 0 if de_inst.debugger_data['debug_type'] == 'indirect' else 1
 
     """
     Animations and transitions are not automatically GPU accelerated and by
@@ -572,12 +550,11 @@ def direct_new(trans_id):
 
     function_arguments = '('
     if 'functionData' in session:
-        session_function_data = session['functionData'][str(trans_id)]
-        if 'args_name' in session_function_data and \
-            session_function_data['args_name'] is not None and \
-                session_function_data['args_name'] != '':
-            args_name_list = session_function_data['args_name'].split(",")
-            args_type_list = session_function_data['args_type'].split(",")
+        if 'args_name' in de_inst.function_data and \
+            de_inst.function_data['args_name'] is not None and \
+                de_inst.function_data['args_name'] != '':
+            args_name_list = de_inst.function_data['args_name'].split(",")
+            args_type_list = de_inst.function_data['args_type'].split(",")
             index = 0
             for args_name in args_name_list:
                 function_arguments = '{}{} {}, '.format(function_arguments,
@@ -592,34 +569,38 @@ def direct_new(trans_id):
 
     layout = get_setting('Debugger/Layout')
 
+    function_name_with_arguments = \
+        de_inst.debugger_data['function_name'] + function_arguments
+
     return render_template(
         "debugger/direct.html",
         _=gettext,
-        function_name=obj['function_name'],
+        function_name=de_inst.debugger_data['function_name'],
         uniqueId=trans_id,
         debug_type=debug_type,
         is_desktop_mode=current_app.PGADMIN_RUNTIME,
         is_linux=is_linux_platform,
         client_platform=user_agent.platform,
-        function_name_with_arguments=obj['function_name'] + function_arguments,
+        function_name_with_arguments=function_name_with_arguments,
         layout=layout
     )
 
 
 @blueprint.route(
-    '/initialize_target/<debug_type>/<int:sid>/<int:did>/<int:scid>/'
-    '<int:func_id>',
+    '/initialize_target/<debug_type>/<int:trans_id>/<int:sid>/<int:did>/'
+    '<int:scid>/<int:func_id>',
     methods=['GET', 'POST'],
     endpoint='initialize_target_for_function'
 )
 @blueprint.route(
-    '/initialize_target/<debug_type>/<int:sid>/<int:did>/<int:scid>/'
-    '<int:func_id>/<int:tri_id>',
+    '/initialize_target/<debug_type>/<int:trans_id>/<int:sid>/<int:did>/'
+    '<int:scid>/<int:func_id>/<int:tri_id>',
     methods=['GET', 'POST'],
     endpoint='initialize_target_for_trigger'
 )
 @login_required
-def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
+def initialize_target(debug_type, trans_id, sid, did,
+                      scid, func_id, tri_id=None):
     """
     initialize_target(debug_type, sid, did, scid, func_id, tri_id)
 
@@ -718,16 +699,6 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
 
         func_id = tr_set['rows'][0]['tgfoid']
 
-    # Create a unique id for the transaction
-    trans_id = str(random.randint(1, 9999999))
-
-    # If there is no debugging information in session variable then create
-    # the store that information
-    if 'debuggerData' not in session:
-        debugger_data = dict()
-    else:
-        debugger_data = session['debuggerData']
-
     status = True
 
     # Find out the debugger version and store it in session variables
@@ -756,6 +727,7 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
     # Add the debugger version information to pgadmin4 log file
     current_app.logger.debug("Debugger version is: %d", debugger_version)
 
+    de_inst = DebuggerInstance(trans_id)
     # We need to pass the value entered by the user in dialog for direct
     # debugging, Here we get the value in case of direct debugging so update
     # the session variables accordingly, For indirect debugging user will
@@ -764,65 +736,26 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
     if request.method == 'POST':
         data = json.loads(request.values['data'], encoding='utf-8')
         if data:
-            d = session['funcData']
-            d['args_value'] = data
-            session['funcData'] = d
+            de_inst.function_data['args_value'] = data
 
     # Update the debugger data session variable
     # Here frame_id is required when user debug the multilevel function.
     # When user select the frame from client we need to update the frame
     # here and set the breakpoint information on that function oid
-    debugger_data[str(trans_id)] = {
+    de_inst.debugger_data = {
         'conn_id': conn_id,
         'server_id': sid,
         'database_id': did,
         'schema_id': scid,
         'function_id': func_id,
-        'function_name': session['funcData']['name'],
+        'function_name': de_inst.function_data['name'],
         'debug_type': debug_type,
         'debugger_version': debugger_version,
         'frame_id': 0,
         'restart_debug': 0
     }
 
-    # Store the grid dictionary into the session variable
-    session['debuggerData'] = debugger_data
-
-    # Update the function session  information with same transaction id
-    func_data = session['funcData']
-
-    # Store the function information in session variable
-    if 'functionData' not in session:
-        function_data = dict()
-    else:
-        function_data = session['functionData']
-
-    function_data[str(trans_id)] = {
-        'oid': func_data['oid'],
-        'name': func_data['name'],
-        'is_func': func_data['is_func'],
-        'is_ppas_database': func_data['is_ppas_database'],
-        'is_callable': func_data['is_callable'],
-        'schema': func_data['schema'],
-        'language': func_data['language'],
-        'return_type': func_data['return_type'],
-        'args_type': func_data['args_type'],
-        'args_name': func_data['args_name'],
-        'arg_mode': func_data['arg_mode'],
-        'use_default': func_data['use_default'],
-        'default_value': func_data['default_value'],
-        'pkgname': func_data['pkgname'],
-        'pkg': func_data['pkg'],
-        'require_input': func_data['require_input'],
-        'args_value': func_data['args_value']
-    }
-
-    # Update the session variable of function information
-    session['functionData'] = function_data
-
-    # Delete the 'funcData' session variables as it is not used now as target
-    # is initialized
-    del session['funcData']
+    de_inst.update_session()
 
     return make_json_response(data={'status': status,
                                     'debuggerTransId': trans_id})
@@ -843,24 +776,9 @@ def close(trans_id):
         trans_id
         - unique transaction id.
     """
-    # As debugger data is not in session that means we have already
-    # deleted and close the target
-    if 'debuggerData' not in session:
-        return make_json_response(data={'status': True})
-
-    # Return from the function if transaction id not found
-    if str(trans_id) not in session['debuggerData']:
-        return make_json_response(data={'status': True})
 
-    with debugger_close_session_lock:
-        try:
-            close_debugger_session(trans_id)
-            # Delete the existing debugger data in session variable
-            del session['debuggerData'][str(trans_id)]
-            del session['functionData'][str(trans_id)]
-            return make_json_response(data={'status': True})
-        except Exception as e:
-            return internal_server_error(errormsg=str(e))
+    close_debugger_session(trans_id)
+    return make_json_response(data={'status': True})
 
 
 @blueprint.route(
@@ -878,8 +796,8 @@ def restart_debugging(trans_id):
         - Transaction ID
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': False,
@@ -889,44 +807,39 @@ def restart_debugging(trans_id):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
-    conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
+    conn = manager.connection(
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['conn_id'])
 
     if conn.connected():
         # Update the session variable "restart_debug" to know that same
         # function debugging has been restarted. Delete the existing debugger
         # data in session variable and update with new data
-        if obj['restart_debug'] == 0:
-            debugger_data = session['debuggerData']
-            session_obj = debugger_data[str(trans_id)]
-            session_obj['restart_debug'] = 1
-            update_session_debugger_transaction(trans_id, session_obj)
-
-        # Store the function information in session variable
-        if 'functionData' not in session:
-            function_data = dict()
-        else:
-            session_function_data = session['functionData'][str(trans_id)]
-            function_data = {
-                'server_id': obj['server_id'],
-                'database_id': obj['database_id'],
-                'schema_id': obj['schema_id'],
-                'function_id': obj['function_id'],
-                'trans_id': str(trans_id),
-                'proargmodes': session_function_data['arg_mode'],
-                'proargtypenames': session_function_data['args_type'],
-                'pronargdefaults': session_function_data['use_default'],
-                'proargdefaults': session_function_data['default_value'],
-                'proargnames': session_function_data['args_name'],
-                'require_input': session_function_data['require_input']
-            }
+        if de_inst.debugger_data['restart_debug'] == 0:
+            de_inst.debugger_data['restart_debug'] = 1
+            de_inst.update_session()
+
+        de_inst.function_data = {
+            'server_id': de_inst.debugger_data['server_id'],
+            'database_id': de_inst.debugger_data['database_id'],
+            'schema_id': de_inst.debugger_data['schema_id'],
+            'function_id': de_inst.debugger_data['function_id'],
+            'trans_id': str(trans_id),
+            'proargmodes': de_inst.function_data['arg_mode'],
+            'proargtypenames': de_inst.function_data['args_type'],
+            'pronargdefaults': de_inst.function_data['use_default'],
+            'proargdefaults': de_inst.function_data['default_value'],
+            'proargnames': de_inst.function_data['args_name'],
+            'require_input': de_inst.function_data['require_input']
+        }
 
         return make_json_response(
             data={
-                'status': True, 'restart_debug': True, 'result': function_data
+                'status': True, 'restart_debug': True,
+                'result': de_inst.function_data
             }
         )
     else:
@@ -935,8 +848,7 @@ def restart_debugging(trans_id):
             'Not connected to server or connection with the server has '
             'been closed.'
         )
-
-    return make_json_response(data={'status': status})
+        return make_json_response(data={'status': status, 'result': result})
 
 
 @blueprint.route(
@@ -956,8 +868,8 @@ def start_debugger_listener(trans_id):
         - Transaction ID
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': False,
@@ -967,17 +879,18 @@ def start_debugger_listener(trans_id):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
 
     driver = get_driver(PG_DEFAULT_DRIVER)
-    manager = driver.connection_manager(obj['server_id'])
-    conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+    manager = driver.connection_manager(de_inst.debugger_data['server_id'])
+    conn = manager.connection(
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['conn_id'])
 
     ver = manager.version
     server_type = manager.server_type
 
     # find the debugger version and execute the query accordingly
-    dbg_version = obj['debugger_version']
+    dbg_version = de_inst.debugger_data['debugger_version']
     if dbg_version <= 2:
         template_path = 'debugger/sql/v1'
     else:
@@ -988,94 +901,91 @@ def start_debugger_listener(trans_id):
     if request.method == 'POST':
         data = json.loads(request.values['data'], encoding='utf-8')
         if data:
-            function_data = session['functionData']
-            session_obj = function_data[str(trans_id)]
-            session_obj['args_value'] = data
-            update_session_function_transaction(trans_id, session_obj)
+            de_inst.function_data['args_value'] = data
+            de_inst.update_session()
 
     if conn.connected():
 
         # For the direct debugging extract the function arguments values from
         # user and pass to jinja template to create the query for execution.
-        if obj['debug_type'] == 'direct':
+        if de_inst.debugger_data['debug_type'] == 'direct':
             str_query = ''
-            session_function_data = session['functionData'][str(trans_id)]
-            if session_function_data['pkg'] == 0:
+            if de_inst.function_data['pkg'] == 0:
                 # Form the function name with schema name
                 func_name = driver.qtIdent(
                     conn,
-                    session_function_data['schema'],
-                    session_function_data['name']
+                    de_inst.function_data['schema'],
+                    de_inst.function_data['name']
                 )
             else:
                 # Form the edb package function/procedure name with schema name
                 func_name = driver.qtIdent(
-                    conn, session_function_data['schema'],
-                    session_function_data['pkgname'],
-                    session_function_data['name']
+                    conn, de_inst.function_data['schema'],
+                    de_inst.function_data['pkgname'],
+                    de_inst.function_data['name']
                 )
 
-            if obj['restart_debug'] == 0:
+            if de_inst.debugger_data['restart_debug'] == 0:
                 # render the SQL template and send the query to server
-                if session_function_data['language'] == 'plpgsql':
+                if de_inst.function_data['language'] == 'plpgsql':
                     sql = render_template(
                         "/".join([template_path,
                                   'debug_plpgsql_execute_target.sql']),
-                        packge_oid=session_function_data['pkg'],
-                        function_oid=obj['function_id']
+                        packge_oid=de_inst.function_data['pkg'],
+                        function_oid=de_inst.debugger_data['function_id']
                     )
                 else:
                     sql = render_template(
                         "/".join([template_path,
                                   'debug_spl_execute_target.sql']),
-                        packge_oid=session_function_data['pkg'],
-                        function_oid=obj['function_id']
+                        packge_oid=de_inst.function_data['pkg'],
+                        function_oid=de_inst.debugger_data['function_id']
                     )
                 status, res = conn.execute_dict(sql)
                 if not status:
                     return internal_server_error(errormsg=res)
 
-            if session_function_data['arg_mode']:
+            if de_inst.function_data['arg_mode']:
                 # In EDBAS 90, if an SPL-function has both an OUT-parameter
                 # and a return value (which is not possible on PostgreSQL
                 # otherwise), the return value is transformed into an extra
                 # OUT-parameter named "_retval_"
-                if session_function_data['args_name']:
-                    arg_name = session_function_data['args_name'].split(",")
+                if de_inst.function_data['args_name']:
+                    arg_name = de_inst.function_data['args_name'].split(",")
                     if '_retval_' in arg_name:
-                        arg_mode = session_function_data['arg_mode'].split(",")
+                        arg_mode = de_inst.function_data['arg_mode'].split(",")
                         arg_mode.pop()
                     else:
-                        arg_mode = session_function_data['arg_mode'].split(",")
+                        arg_mode = de_inst.function_data['arg_mode'].split(",")
                 else:
-                    arg_mode = session_function_data['arg_mode'].split(",")
+                    arg_mode = de_inst.function_data['arg_mode'].split(",")
             else:
                 arg_mode = ['i'] * len(
-                    session_function_data['args_type'].split(",")
+                    de_inst.function_data['args_type'].split(",")
                 )
 
-            if session_function_data['args_type']:
-                if session_function_data['args_name']:
-                    arg_name = session_function_data['args_name'].split(",")
+            if de_inst.function_data['args_type']:
+                if de_inst.function_data['args_name']:
+                    arg_name = de_inst.function_data['args_name'].split(",")
                     if '_retval_' in arg_name:
-                        arg_type = session_function_data[
+                        arg_type = de_inst.function_data[
                             'args_type'].split(",")
                         arg_type.pop()
                     else:
-                        arg_type = session_function_data[
+                        arg_type = de_inst.function_data[
                             'args_type'].split(",")
                 else:
-                    arg_type = session_function_data['args_type'].split(",")
+                    arg_type = de_inst.function_data['args_type'].split(",")
 
             # Below are two different template to execute and start executer
             if manager.server_type != 'pg' and manager.version < 90300:
                 str_query = render_template(
                     "/".join(['debugger/sql', 'execute_edbspl.sql']),
                     func_name=func_name,
-                    is_func=session_function_data['is_func'],
-                    lan_name=session_function_data['language'],
-                    ret_type=session_function_data['return_type'],
-                    data=session_function_data['args_value'],
+                    is_func=de_inst.function_data['is_func'],
+                    lan_name=de_inst.function_data['language'],
+                    ret_type=de_inst.function_data['return_type'],
+                    data=de_inst.function_data['args_value'],
                     arg_type=arg_type,
                     args_mode=arg_mode
                 )
@@ -1083,10 +993,10 @@ def start_debugger_listener(trans_id):
                 str_query = render_template(
                     "/".join(['debugger/sql', 'execute_plpgsql.sql']),
                     func_name=func_name,
-                    is_func=session_function_data['is_func'],
-                    ret_type=session_function_data['return_type'],
-                    data=session_function_data['args_value'],
-                    is_ppas_database=session_function_data['is_ppas_database']
+                    is_func=de_inst.function_data['is_func'],
+                    ret_type=de_inst.function_data['return_type'],
+                    data=de_inst.function_data['args_value'],
+                    is_ppas_database=de_inst.function_data['is_ppas_database']
                 )
 
             status, result = conn.execute_async(str_query)
@@ -1144,13 +1054,12 @@ def start_debugger_listener(trans_id):
                 if not status:
                     return internal_server_error(errormsg=res)
 
-                debugger_data = session['debuggerData']
-                session_obj = debugger_data[str(trans_id)]
-                session_obj['exe_conn_id'] = obj['conn_id']
-                session_obj['restart_debug'] = 1
-                session_obj['frame_id'] = 0
-                session_obj['session_id'] = int_session_id
-                update_session_debugger_transaction(trans_id, session_obj)
+                de_inst.debugger_data['exe_conn_id'] = \
+                    de_inst.debugger_data['conn_id']
+                de_inst.debugger_data['restart_debug'] = 1
+                de_inst.debugger_data['frame_id'] = 0
+                de_inst.debugger_data['session_id'] = int_session_id
+                de_inst.update_session()
                 return make_json_response(
                     data={'status': status, 'result': res}
                 )
@@ -1196,8 +1105,8 @@ def execute_debugger_query(trans_id, query_type):
         - Type of query to execute
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': False,
@@ -1207,15 +1116,15 @@ def execute_debugger_query(trans_id, query_type):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
     conn = manager.connection(
-        did=obj['database_id'], conn_id=obj['exe_conn_id'])
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['exe_conn_id'])
 
     # find the debugger version and execute the query accordingly
-    dbg_version = obj['debugger_version']
+    dbg_version = de_inst.debugger_data['debugger_version']
     if dbg_version <= 2:
         template_path = 'debugger/sql/v1'
     else:
@@ -1224,7 +1133,7 @@ def execute_debugger_query(trans_id, query_type):
     if conn.connected():
         sql = render_template(
             "/".join([template_path, query_type + ".sql"]),
-            session_id=obj['session_id']
+            session_id=de_inst.debugger_data['session_id']
         )
         # As the query type is continue or step_into or step_over then we
         # may get result after some time so poll the result.
@@ -1233,10 +1142,9 @@ def execute_debugger_query(trans_id, query_type):
         if query_type == 'continue' or query_type == 'step_into' or \
                 query_type == 'step_over':
             # We should set the frame_id to 0 when execution starts.
-            if obj['frame_id'] != 0:
-                session_obj = debugger_data[str(trans_id)]
-                session_obj['frame_id'] = 0
-                update_session_debugger_transaction(trans_id, session_obj)
+            if de_inst.debugger_data['frame_id'] != 0:
+                de_inst.debugger_data['frame_id'] = 0
+                de_inst.update_session()
 
             status, result = conn.execute_async(sql)
             if not status:
@@ -1282,8 +1190,8 @@ def messages(trans_id):
         - unique transaction id.
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': 'NotConnected',
@@ -1293,11 +1201,12 @@ def messages(trans_id):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
-    conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
+    conn = manager.connection(
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['conn_id'])
 
     port_number = ''
 
@@ -1357,8 +1266,8 @@ def start_execution(trans_id, port_num):
         - Port number to attach
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': 'NotConnected',
@@ -1368,16 +1277,15 @@ def start_execution(trans_id, port_num):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
-
-    dbg_version = obj['debugger_version']
 
     # Create asynchronous connection using random connection id.
     exe_conn_id = str(random.randint(1, 9999999))
     try:
-        manager = get_driver(
-            PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
-        conn = manager.connection(did=obj['database_id'], conn_id=exe_conn_id)
+        manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+            de_inst.debugger_data['server_id'])
+        conn = manager.connection(
+            did=de_inst.debugger_data['database_id'],
+            conn_id=exe_conn_id)
     except Exception as e:
         return internal_server_error(errormsg=str(e))
 
@@ -1386,13 +1294,8 @@ def start_execution(trans_id, port_num):
     if not status:
         return internal_server_error(errormsg=str(msg))
 
-    if 'debuggerData' not in session:
-        debugger_data = dict()
-    else:
-        debugger_data = session['debuggerData']
-
     # find the debugger version and execute the query accordingly
-    dbg_version = obj['debugger_version']
+    dbg_version = de_inst.debugger_data['debugger_version']
     if dbg_version <= 2:
         template_path = 'debugger/sql/v1'
     else:
@@ -1405,13 +1308,13 @@ def start_execution(trans_id, port_num):
     if not status_port:
         return internal_server_error(errormsg=res_port)
 
-    session_obj = debugger_data[str(trans_id)]
-    session_obj['restart_debug'] = 0
-    session_obj['frame_id'] = 0
-    session_obj['exe_conn_id'] = exe_conn_id
-    session_obj['debugger_version'] = dbg_version
-    session_obj['session_id'] = res_port['rows'][0]['pldbg_attach_to_port']
-    update_session_debugger_transaction(trans_id, session_obj)
+    de_inst.debugger_data['restart_debug'] = 0
+    de_inst.debugger_data['frame_id'] = 0
+    de_inst.debugger_data['exe_conn_id'] = exe_conn_id
+    de_inst.debugger_data['debugger_version'] = dbg_version
+    de_inst.debugger_data['session_id'] = \
+        res_port['rows'][0]['pldbg_attach_to_port']
+    de_inst.update_session()
 
     return make_json_response(
         data={
@@ -1441,8 +1344,9 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
         - 0 - clear the breakpoint, 1 - set the breakpoint
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': False,
@@ -1452,15 +1356,15 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
     conn = manager.connection(
-        did=obj['database_id'], conn_id=obj['exe_conn_id'])
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['exe_conn_id'])
 
     # find the debugger version and execute the query accordingly
-    dbg_version = obj['debugger_version']
+    dbg_version = de_inst.debugger_data['debugger_version']
     if dbg_version <= 2:
         template_path = 'debugger/sql/v1'
     else:
@@ -1474,7 +1378,7 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
     # session variable and pass tha appropriate foid to set the breakpoint.
     sql_ = render_template(
         "/".join([template_path, "get_stack_info.sql"]),
-        session_id=obj['session_id']
+        session_id=de_inst.debugger_data['session_id']
     )
     status, res_stack = conn.execute_dict(sql_)
     if not status:
@@ -1483,7 +1387,7 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
     # For multilevel function debugging, we need to fetch current selected
     # frame's function oid for setting the breakpoint. For single function
     # the frame id will be 0.
-    foid = res_stack['rows'][obj['frame_id']]['func']
+    foid = res_stack['rows'][de_inst.debugger_data['frame_id']]['func']
 
     # Check the result of the stack before setting the breakpoint
     if conn.connected():
@@ -1494,7 +1398,7 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
 
         sql = render_template(
             "/".join([template_path, query_type + ".sql"]),
-            session_id=obj['session_id'],
+            session_id=de_inst.debugger_data['session_id'],
             foid=foid, line_number=line_no
         )
 
@@ -1528,8 +1432,9 @@ def clear_all_breakpoint(trans_id):
         trans_id
         - Transaction ID
     """
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': False,
@@ -1539,22 +1444,19 @@ def clear_all_breakpoint(trans_id):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
-
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
     conn = manager.connection(
-        did=obj['database_id'], conn_id=obj['exe_conn_id'])
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['exe_conn_id'])
 
     # find the debugger version and execute the query accordingly
-    dbg_version = obj['debugger_version']
+    dbg_version = de_inst.debugger_data['debugger_version']
     if dbg_version <= 2:
         template_path = 'debugger/sql/v1'
     else:
         template_path = 'debugger/sql/v2'
 
-    query_type = ''
-
     if conn.connected():
         # get the data sent through post from client
         if request.form['breakpoint_list']:
@@ -1562,8 +1464,9 @@ def clear_all_breakpoint(trans_id):
             for line_no in line_numbers:
                 sql = render_template(
                     "/".join([template_path, "clear_breakpoint.sql"]),
-                    session_id=obj['session_id'],
-                    foid=obj['function_id'], line_number=line_no
+                    session_id=de_inst.debugger_data['session_id'],
+                    foid=de_inst.debugger_data['function_id'],
+                    line_number=line_no
                 )
 
                 status, result = conn.execute_dict(sql)
@@ -1597,8 +1500,9 @@ def deposit_parameter_value(trans_id):
         trans_id
         - Transaction ID
     """
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': False,
@@ -1606,22 +1510,19 @@ def deposit_parameter_value(trans_id):
                                   'with the server has been closed.')
             }
         )
-    obj = debugger_data[str(trans_id)]
-
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
     conn = manager.connection(
-        did=obj['database_id'], conn_id=obj['exe_conn_id'])
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['exe_conn_id'])
 
     # find the debugger version and execute the query accordingly
-    dbg_version = obj['debugger_version']
+    dbg_version = de_inst.debugger_data['debugger_version']
     if dbg_version <= 2:
         template_path = 'debugger/sql/v1'
     else:
         template_path = 'debugger/sql/v2'
 
-    query_type = ''
-
     if conn.connected():
         # get the data sent through post from client
         data = json.loads(request.values['data'], encoding='utf-8')
@@ -1629,7 +1530,7 @@ def deposit_parameter_value(trans_id):
         if data:
             sql = render_template(
                 "/".join([template_path, "deposit_value.sql"]),
-                session_id=obj['session_id'],
+                session_id=de_inst.debugger_data['session_id'],
                 var_name=data[0]['name'], line_number=-1,
                 val=data[0]['value']
             )
@@ -1678,8 +1579,8 @@ def select_frame(trans_id, frame_id):
         frame_id
         - Frame id selected
     """
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': False,
@@ -1689,28 +1590,27 @@ def select_frame(trans_id, frame_id):
                 )
             }
         )
-    obj = debugger_data[str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
     conn = manager.connection(
-        did=obj['database_id'], conn_id=obj['exe_conn_id'])
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['exe_conn_id'])
 
     # find the debugger version and execute the query accordingly
-    dbg_version = obj['debugger_version']
+    dbg_version = de_inst.debugger_data['debugger_version']
     if dbg_version <= 2:
         template_path = 'debugger/sql/v1'
     else:
         template_path = 'debugger/sql/v2'
 
-    session_obj = debugger_data[str(trans_id)]
-    session_obj['frame_id'] = frame_id
-    update_session_debugger_transaction(trans_id, session_obj)
+    de_inst.debugger_data['frame_id'] = frame_id
+    de_inst.update_session()
 
     if conn.connected():
         sql = render_template(
             "/".join([template_path, "select_frame.sql"]),
-            session_id=obj['session_id'],
+            session_id=de_inst.debugger_data['session_id'],
             frame_id=frame_id
         )
 
@@ -1950,8 +1850,8 @@ def poll_end_execution_result(trans_id):
         - unique transaction id.
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={'status': 'NotConnected',
                   'result': gettext(
@@ -1959,11 +1859,12 @@ def poll_end_execution_result(trans_id):
                       'server has been closed.')
                   }
         )
-    obj = debugger_data[str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
-    conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
+    conn = manager.connection(
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['conn_id'])
 
     if conn.connected():
         statusmsg = conn.status_message()
@@ -1980,11 +1881,10 @@ def poll_end_execution_result(trans_id):
                 }
             )
 
-        session_function_data = session['functionData'][str(trans_id)]
         if status == ASYNC_OK and \
-            not session_function_data['is_func'] and\
-            (session_function_data['language'] == 'edbspl' or
-                session_function_data['language'] == 'plpgsql'):
+            not de_inst.function_data['is_func'] and\
+            (de_inst.function_data['language'] == 'edbspl' or
+                de_inst.function_data['language'] == 'plpgsql'):
             status = 'Success'
             additional_msgs = conn.messages()
             if len(additional_msgs) > 0:
@@ -2077,8 +1977,8 @@ def poll_result(trans_id):
         - unique transaction id.
     """
 
-    debugger_data = session['debuggerData']
-    if str(trans_id) not in debugger_data:
+    de_inst = DebuggerInstance(trans_id)
+    if de_inst.debugger_data is None:
         return make_json_response(
             data={
                 'status': 'NotConnected',
@@ -2086,12 +1986,12 @@ def poll_result(trans_id):
                                   'with the server has been closed.')
             }
         )
-    obj = debugger_data[str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+        de_inst.debugger_data['server_id'])
     conn = manager.connection(
-        did=obj['database_id'], conn_id=obj['exe_conn_id'])
+        did=de_inst.debugger_data['database_id'],
+        conn_id=de_inst.debugger_data['exe_conn_id'])
 
     if conn.connected():
         status, result = conn.poll()
@@ -2117,7 +2017,7 @@ def poll_result(trans_id):
     )
 
 
-def close_debugger_session(trans_id):
+def close_debugger_session(_trans_id, close_all=False):
     """
     This function is used to cancel the debugger transaction and
     release the connection.
@@ -2125,21 +2025,39 @@ def close_debugger_session(trans_id):
     :param trans_id: Transaction id
     :return:
     """
-    dbg_obj = session['debuggerData'][str(trans_id)]
 
-    manager = get_driver(
-        PG_DEFAULT_DRIVER).connection_manager(dbg_obj['server_id'])
+    if close_all:
+        trans_ids = DebuggerInstance.get_trans_ids()
+    else:
+        trans_ids = [_trans_id]
 
-    if manager is not None:
-        conn = manager.connection(
-            did=dbg_obj['database_id'], conn_id=dbg_obj['conn_id'])
-        if conn.connected():
-            conn.cancel_transaction(dbg_obj['conn_id'],
-                                    dbg_obj['database_id'])
-        conn = manager.connection(
-            did=dbg_obj['database_id'], conn_id=dbg_obj['exe_conn_id'])
-        if conn.connected():
-            conn.cancel_transaction(dbg_obj['exe_conn_id'],
-                                    dbg_obj['database_id'])
-        manager.release(conn_id=dbg_obj['conn_id'])
-        manager.release(conn_id=dbg_obj['exe_conn_id'])
+    for trans_id in trans_ids:
+        de_inst = DebuggerInstance(trans_id)
+        dbg_obj = de_inst.debugger_data
+
+        try:
+            if dbg_obj is not None:
+                manager = get_driver(PG_DEFAULT_DRIVER).\
+                    connection_manager(dbg_obj['server_id'])
+
+                if manager is not None:
+                    conn = manager.connection(
+                        did=dbg_obj['database_id'],
+                        conn_id=dbg_obj['conn_id'])
+                    if conn.connected():
+                        conn.cancel_transaction(
+                            dbg_obj['conn_id'],
+                            dbg_obj['database_id'])
+                    conn = manager.connection(
+                        did=dbg_obj['database_id'],
+                        conn_id=dbg_obj['exe_conn_id'])
+                    if conn.connected():
+                        conn.cancel_transaction(
+                            dbg_obj['exe_conn_id'],
+                            dbg_obj['database_id'])
+                    manager.release(conn_id=dbg_obj['conn_id'])
+                    manager.release(conn_id=dbg_obj['exe_conn_id'])
+        except Exception as _:
+            raise
+        finally:
+            de_inst.clear()
diff --git a/web/pgadmin/tools/debugger/static/js/debugger.js b/web/pgadmin/tools/debugger/static/js/debugger.js
index 2ee1d55c..c91e418f 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger.js
@@ -343,17 +343,17 @@ define([
       var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
         baseUrl;
 
-      if (d._type == 'function') {
+      if (d._type == 'function' || d._type == 'edbfunc') {
         baseUrl = url_for(
           'debugger.initialize_target_for_function', {
             'debug_type': 'indirect',
             'sid': treeInfo.server._id,
             'did': treeInfo.database._id,
             'scid': treeInfo.schema._id,
-            'func_id': treeInfo.function._id,
+            'func_id': debuggerUtils.getFunctionId(treeInfo),
           }
         );
-      } else if (d._type == 'procedure') {
+      } else if (d._type == 'procedure' || d._type == 'edbproc') {
         baseUrl = url_for(
           'debugger.initialize_target_for_function', {
             'debug_type': 'indirect',
@@ -363,24 +363,6 @@ define([
             'func_id': debuggerUtils.getProcedureId(treeInfo),
           }
         );
-      } else if (d._type == 'edbfunc') {
-        // Get the existing function parameters available from sqlite database
-        baseUrl = url_for('debugger.initialize_target_for_function', {
-          'debug_type': 'indirect',
-          'sid': treeInfo.server._id,
-          'did': treeInfo.database._id,
-          'scid': treeInfo.schema._id,
-          'func_id': treeInfo.edbfunc._id,
-        });
-      } else if (d._type == 'edbproc') {
-        // Get the existing function parameters available from sqlite database
-        baseUrl = url_for('debugger.initialize_target_for_function', {
-          'debug_type': 'indirect',
-          'sid': treeInfo.server._id,
-          'did': treeInfo.database._id,
-          'scid': treeInfo.schema._id,
-          'func_id': treeInfo.edbproc._id,
-        });
       } else if (d._type == 'trigger_function') {
         baseUrl = url_for(
           'debugger.initialize_target_for_function', {
@@ -491,9 +473,11 @@ define([
       })
         .done(function(res) {
 
+          let debug_info = res.data.debug_info,
+            trans_id = res.data.trans_id;
           // Open Alertify the dialog to take the input arguments from user if function having input arguments
-          if (res.data[0]['require_input']) {
-            get_function_arguments(res.data[0], 0, is_edb_proc);
+          if (debug_info[0]['require_input']) {
+            get_function_arguments(debug_info[0], 0, is_edb_proc, trans_id);
           } else {
           // Initialize the target and create asynchronous connection and unique transaction ID
           // If there is no arguments to the functions then we should not ask for for function arguments and
@@ -509,20 +493,22 @@ define([
             var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
               baseUrl;
 
-            if (d._type == 'function') {
+            if (d._type == 'function' || d._type == 'edbfunc') {
               baseUrl = url_for(
                 'debugger.initialize_target_for_function', {
                   'debug_type': 'direct',
+                  'trans_id': trans_id,
                   'sid': treeInfo.server._id,
                   'did': treeInfo.database._id,
                   'scid': treeInfo.schema._id,
-                  'func_id': treeInfo.function._id,
+                  'func_id': debuggerUtils.getFunctionId(treeInfo),
                 }
               );
-            } else {
+            } else if(d._type == 'procedure' || d._type == 'edbproc') {
               baseUrl = url_for(
                 'debugger.initialize_target_for_function', {
                   'debug_type': 'direct',
+                  'trans_id': trans_id,
                   'sid': treeInfo.server._id,
                   'did': treeInfo.database._id,
                   'scid': treeInfo.schema._id,
@@ -535,10 +521,10 @@ define([
               url: baseUrl,
               method: 'GET',
             })
-              .done(function(res) {
+              .done(function() {
 
                 var url = url_for('debugger.direct', {
-                  'trans_id': res.data.debuggerTransId,
+                  'trans_id': trans_id,
                 });
 
                 if (self.preferences.debugger_new_browser_tab) {
@@ -563,7 +549,7 @@ define([
                   // Register Panel Closed event
                   panel.on(wcDocker.EVENT.CLOSED, function() {
                     var closeUrl = url_for('debugger.close', {
-                      'trans_id': res.data.debuggerTransId,
+                      'trans_id': trans_id,
                     });
                     $.ajax({
                       url: closeUrl,
diff --git a/web/pgadmin/tools/debugger/static/js/debugger_ui.js b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
index 46d34eed..f05a22dc 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger_ui.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
@@ -163,11 +163,11 @@ define([
     }
   };
 
-  var res = function(debug_info, restart_debug, is_edb_proc) {
+  var res = function(debug_info, restart_debug, is_edb_proc, trans_id) {
     if (!Alertify.debuggerInputArgsDialog) {
       Alertify.dialog('debuggerInputArgsDialog', function factory() {
         return {
-          main: function(title, debug_info, restart_debug, is_edb_proc) {
+          main: function(title, debug_info, restart_debug, is_edb_proc, trans_id) {
             this.preferences = window.top.pgAdmin.Browser.get_preferences_for_module('debugger');
             this.set('title', title);
 
@@ -175,6 +175,7 @@ define([
             // other functions other than main function.
             this.set('debug_info', debug_info);
             this.set('restart_debug', restart_debug);
+            this.set('trans_id', trans_id);
 
             // Variables to store the data sent from sqlite database
             var func_args_data = this.func_args_data = [];
@@ -579,6 +580,7 @@ define([
           settings: {
             debug_info: undefined,
             restart_debug: undefined,
+            trans_id: undefined,
           },
           setup: function() {
             return {
@@ -706,6 +708,7 @@ define([
                 if (d._type == 'function') {
                   baseUrl = url_for('debugger.initialize_target_for_function', {
                     'debug_type': 'direct',
+                    'trans_id': self.setting('trans_id'),
                     'sid': treeInfo.server._id,
                     'did': treeInfo.database._id,
                     'scid': treeInfo.schema._id,
@@ -714,6 +717,7 @@ define([
                 } else if (d._type == 'procedure') {
                   baseUrl = url_for('debugger.initialize_target_for_function', {
                     'debug_type': 'direct',
+                    'trans_id': self.setting('trans_id'),
                     'sid': treeInfo.server._id,
                     'did': treeInfo.database._id,
                     'scid': treeInfo.schema._id,
@@ -722,6 +726,7 @@ define([
                 } else if (d._type == 'edbfunc') {
                   baseUrl = url_for('debugger.initialize_target_for_function', {
                     'debug_type': 'direct',
+                    'trans_id': self.setting('trans_id'),
                     'sid': treeInfo.server._id,
                     'did': treeInfo.database._id,
                     'scid': treeInfo.schema._id,
@@ -730,6 +735,7 @@ define([
                 } else if (d._type == 'edbproc') {
                   baseUrl = url_for('debugger.initialize_target_for_function', {
                     'debug_type': 'direct',
+                    'trans_id': self.setting('trans_id'),
                     'sid': treeInfo.server._id,
                     'did': treeInfo.database._id,
                     'scid': treeInfo.schema._id,
@@ -885,7 +891,12 @@ define([
             }
 
             if (e.button.text === gettext('Cancel')) {
-              //close the dialog...
+              /* Clear the trans id */
+              $.ajax({
+                method: 'DELETE',
+                url: url_for('debugger.close', {'trans_id': this.setting('trans_id')}),
+              });
+
               return false;
             }
           },
@@ -959,7 +970,7 @@ define([
     }
 
     Alertify.debuggerInputArgsDialog(
-      gettext('Debugger'), debug_info, restart_debug, is_edb_proc
+      gettext('Debugger'), debug_info, restart_debug, is_edb_proc, trans_id
     ).resizeTo(pgBrowser.stdW.md,pgBrowser.stdH.md);
 
   };
diff --git a/web/pgadmin/tools/debugger/static/js/debugger_utils.js b/web/pgadmin/tools/debugger/static/js/debugger_utils.js
index a3529d84..282acb01 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger_utils.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger_utils.js
@@ -18,6 +18,18 @@ function setFocusToDebuggerEditor(editor, command) {
   }
 }
 
+function getFunctionId(treeInfoObject) {
+  let objectId;
+  if(treeInfoObject) {
+    if (treeInfoObject.function && treeInfoObject.function._id) {
+      objectId = treeInfoObject.function._id;
+    } else if (treeInfoObject.edbfunc && treeInfoObject.edbfunc._id) {
+      objectId = treeInfoObject.edbfunc._id;
+    }
+  }
+  return objectId;
+}
+
 function getProcedureId(treeInfoObject) {
   let objectId;
   if(treeInfoObject) {
@@ -32,5 +44,6 @@ function getProcedureId(treeInfoObject) {
 
 module.exports = {
   setFocusToDebuggerEditor: setFocusToDebuggerEditor,
+  getFunctionId: getFunctionId,
   getProcedureId: getProcedureId,
 };
diff --git a/web/pgadmin/tools/debugger/utils/debugger_instance.py b/web/pgadmin/tools/debugger/utils/debugger_instance.py
new file mode 100644
index 00000000..d16021e1
--- /dev/null
+++ b/web/pgadmin/tools/debugger/utils/debugger_instance.py
@@ -0,0 +1,72 @@
+from flask import session
+from threading import Lock
+import random
+
+debugger_sessions_lock = Lock()
+
+
+class DebuggerInstance:
+    def __init__(self, trans_id=None):
+        if trans_id is None:
+            self._trans_id = str(random.randint(1, 9999999))
+        else:
+            self._trans_id = trans_id
+
+        self._function_data = None
+        self._debugger_data = None
+        self.load_from_session()
+
+    @property
+    def trans_id(self):
+        """
+        trans_id be readonly with no setter
+        """
+        return self._trans_id
+
+    @property
+    def function_data(self):
+        return self._function_data
+
+    @function_data.setter
+    def function_data(self, data):
+        self._function_data = data
+        self.update_session()
+
+    @property
+    def debugger_data(self):
+        return self._debugger_data
+
+    @debugger_data.setter
+    def debugger_data(self, data):
+        self._debugger_data = data
+        self.update_session()
+
+    @staticmethod
+    def get_trans_ids():
+        if '__debugger_sessions' in session:
+            return [trans_id for trans_id in session['__debugger_sessions']]
+        else:
+            return []
+
+    def load_from_session(self):
+        if '__debugger_sessions' in session:
+            if str(self.trans_id) in session['__debugger_sessions']:
+                trans_data = session['__debugger_sessions'][str(self.trans_id)]
+                self.function_data = trans_data.get('function_data', None)
+                self.debugger_data = trans_data.get('debugger_data', None)
+
+    def update_session(self):
+        with debugger_sessions_lock:
+            if '__debugger_sessions' not in session:
+                session['__debugger_sessions'] = dict()
+
+            session['__debugger_sessions'][str(self.trans_id)] = dict(
+                function_data=self.function_data,
+                debugger_data=self.debugger_data
+            )
+
+    def clear(self):
+        with debugger_sessions_lock:
+            if '__debugger_sessions' in session:
+                if str(self.trans_id) in session['__debugger_sessions']:
+                    session['__debugger_sessions'].pop(str(self.trans_id))
