diff --git a/README.md b/README.md
index bdcad01a6c9711bfcb674a7058b58ee065787442..f903ebd292a57ff2e956426f7382de04576d6349 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[PACKAGE]: ../../raw/master/mkp/create_topology_data-0.1.0-20231028.mkp "create_topology_data-0.1.0-20231028.mkp"
+[PACKAGE]: ../../raw/master/mkp/create_topology_data-0.2.0-20231116.mkp "create_topology_data-0.2.0-20231116.mkp"
 Network Visualization data creation tool from inventory data
 
 This script creates the topology data file needed for the [Checkmk Exchange Network visualization](https://exchange.checkmk.com/p/network-visualization) plugin by Andreas Boesl and [schnetz](https://exchange.checkmk.com/u/schnetz).\
diff --git a/bin/topology_data/create_topology_args.py b/bin/topology_data/create_topology_args.py
index fd8a8013ef2d9752b9d685b2b8a27759a1dc0323..af60d8655ae25d01e0efe796228f57cf387a92e0 100755
--- a/bin/topology_data/create_topology_args.py
+++ b/bin/topology_data/create_topology_args.py
@@ -9,6 +9,7 @@
 
 #
 # options used
+# -b --backend
 # -d --default
 # -l --layer
 # -o --output-directory
@@ -59,6 +60,16 @@ def parse_arguments() -> arg_Namespace:
     )
     command_group = parser.add_mutually_exclusive_group()
 
+    parser.add_argument(
+        '-b', '--backend',
+        # nargs='+',
+        choices=['LIVESTATUS', 'FILESYSTEM', 'MULTISITE'],
+        default='LIVESTATUS',
+        help=f'Backend used to retrieve the topology data\n'
+             f'LIVESTATUS fetches the data only from the local site. In distributed environments use FILESYSTEM.\n'
+             f'For performance reasons LIVESTATUS is the default.',
+    )
+
     parser.add_argument(
         '-d', '--default', default=False, action='store_const', const=True,
         help='Set the created topology data as default',
diff --git a/bin/topology_data/create_topology_classes.py b/bin/topology_data/create_topology_classes.py
index 14631a5d3aca46dfc875c0ca4a6a493eed99582f..2610eadb4383708fbb98a530117368f6a56a267b 100755
--- a/bin/topology_data/create_topology_classes.py
+++ b/bin/topology_data/create_topology_classes.py
@@ -14,26 +14,27 @@ from pathlib import Path
 from time import strftime
 from typing import Dict, List, Any, NamedTuple
 from enum import Enum, unique
+from abc import abstractmethod
+from ast import literal_eval
+
 from create_topology_utils import (
     CREATE_TOPOLOGY_VERSION,
-    PATH_CDP,
-    PATH_LLDP,
     PATH_INTERFACES,
     USER_DATA_FILE,
-    LQ_INTERFACES,
+    CACHE_INTERFACES_ITEM,
     SCRIPT,
-    get_inventory_data,
+    get_data_form_live_status,
     get_table_from_inventory,
-    get_interface_items_from_lq,
     ExitCodes,
     get_data_from_toml,
+    OMD_ROOT,
 )
 
 
 @unique
-class CacheSources(Enum):
+class CacheItems(Enum):
     inventory = 'inventory'
-    lq = 'lq'
+    interfaces = 'interfaces'
 
 
 class InventoryColumns(NamedTuple):
@@ -59,9 +60,6 @@ class Settings:
         self.__topology_save_path = 'var/topology_data'
         self.__topology_file_name = 'network_data.json'
         self.__path_to_if_table = 'networking,interfaces'
-        # self.__inventory_path = 'var/check_mk/inventory'
-        # self.__autochecks_path = 'var/check_mk/autochecks'
-
         self.__settings = {
             'layers': [],
             'seed_devices': None,
@@ -78,6 +76,7 @@ class Settings:
             'check_user_data_only': False,
             'keep': None,
             'min_age': None,
+            'backend': 'LIVESTATUS',
         }
         # args in the form {'s, __seed_devices': 'CORE01', 'p, __path_in_inventory': None, ... }}
         # we will remove 's, __'
@@ -99,6 +98,10 @@ class Settings:
                 print(f'-l/--layers options must be unique. Don~\'t use any layer more than once.')
                 exit(code=ExitCodes.BAD_OPTION_LIST.value)
 
+    @property
+    def backend(self) -> str:
+        return self.__settings['backend']
+
     @property
     def version(self) -> bool:
         return self.__settings['version']
@@ -186,36 +189,151 @@ class HostCache:
     def __init__(self):
         self.__cache = {}
         self.__inventory_pre_fetch_list: List[str] = [
-            # PATH_CDP,
-            # PATH_LLDP,
             PATH_INTERFACES,
         ]
 
+    @abstractmethod
+    def get_inventory_data(self, host: str, debug: bool = False) -> Dict[str, str] | None:
+        """
+        Args:
+            host: the host name to return the inventory data for
+            debug: enable debug output
+
+        Returns:
+            the inventory data as dictionary
+        """
+
+    @abstractmethod
+    def get_interface_items(self, host: str, debug: bool = False) -> List:
+        """
+
+        Args:
+            host:  the host name to return the interface items
+            debug: enable debug output
+
+        Returns:
+            list of the interface items
+        """
+
     def __fill_cache(self, host: str):
         # pre fill inventory data
-        inventory = get_inventory_data(host=host)
+        inventory = self.get_inventory_data(host=host)
         if inventory:
-            self.__cache[host][CacheSources.inventory.value] = {}
-            self.__cache[host][CacheSources.inventory.value].update({
+            self.__cache[host][CacheItems.inventory.value] = {}
+            self.__cache[host][CacheItems.inventory.value].update({
                 entry: get_table_from_inventory(
                     inventory=inventory,
                     path=entry
                 ) for entry in self.__inventory_pre_fetch_list
             })
         else:
-            self.__cache[host][CacheSources.inventory.value] = None
-        # prefill live status data
-        self.__cache[host][CacheSources.lq.value] = {}
-        self.__cache[host][CacheSources.lq.value][LQ_INTERFACES] = get_interface_items_from_lq(host)
+            self.__cache[host][CacheItems.inventory.value] = None
+        self.__cache[host][CacheItems.interfaces.value] = {}
+        self.__cache[host][CacheItems.interfaces.value][CACHE_INTERFACES_ITEM] = self.get_interface_items(host)
 
-    def get_data(self, host: str, source: CacheSources, path: str):
+    def get_data(self, host: str, item: CacheItems, path: str):
         if host not in self.__cache.keys():
             self.__cache[host]: Dict[str, Any] = {}
             self.__fill_cache(host=host)
         try:
-            return self.__cache[host][source.value][path]
+            return self.__cache[host][item.value][path]
         except (KeyError, TypeError) as _e:
             return None
 
     def add_inventory_prefetch_path(self, path: str):
         self.__inventory_pre_fetch_list = list(set(self.__inventory_pre_fetch_list + [path]))
+
+
+class HostCacheLiveStatus(HostCache):
+    def get_inventory_data(self, host: str, debug: bool = False) -> Dict[str, str] | None:
+        query = f'GET hosts\nColumns: mk_inventory\nOutputFormat: python3\nFilter: host_name = {host}\n'
+        data = get_data_form_live_status(query=query)
+        if data:
+            try:
+                data = literal_eval(data[0][0].decode('utf-8'))
+            except SyntaxError as e:
+                if debug:
+                    print(f'data: |{data}|')
+                    print(f'type: {type(data)}')
+                    print(f'exception: {e}')
+                return
+            return data
+
+    def get_interface_items(self, host: str, debug: bool = False) -> List:
+        """
+        Sample data from lq query, we keep only the item (description without "Interface" ).
+        [
+         ['C9540-7-1', 'Interface Vlan-999', 'check_mk-if64'],
+         ['C9540-7-1', 'Interface Vlan-998', 'check_mk-if64'],
+         ['C9540-7-1', 'Interface Vlan-997', 'check_mk-if64'],
+         ['C9540-7-1', 'Interface Vlan-996', 'check_mk-if64'],
+         ['C9540-7-1', 'Interface Vlan-8', 'check_mk-if64'],
+         ['C9540-7-1', 'Interface Te2/0/2', 'check_mk-if64'],
+         ['C9540-7-1', 'Interface Te2/0/30', 'check_mk-if64']
+         ]
+        Args:
+            host:
+            debug:
+
+        Returns:
+
+        """
+        query = (
+            'GET services\n'
+            'Columns: host_name description check_command\n'
+            'Filter: description ~ Interface\n'
+            f'Filter: host_name = {host}\n'
+            'OutputFormat: python3\n'
+        )
+        data = get_data_form_live_status(query=query)
+        items = []
+        for host, description, check_command in data:
+            items.append(description[10:])  # remove 'Interface ' from description
+
+        if debug:
+            print(f'Interfaces items found: {len(items)} an host {host}')
+        return items
+
+
+class HostCacheFileSystem(HostCache):
+    def get_inventory_data(self, host: str, debug: bool = False) -> Dict[str, str] | None:
+        __inventory_path = 'var/check_mk/inventory'
+        inventory_file = Path(f'{OMD_ROOT}/{__inventory_path}/{host}')
+        if inventory_file.exists():
+            data = literal_eval(inventory_file.read_text())
+            return data
+        else:
+            return None
+
+    def get_interface_items(self, host: str, debug: bool = False) -> List:
+        """
+        Sample autochecks data we keep only the item
+        [
+         {'check_plugin_name': 'if64', 'item': 'Fa0', 'parameters': {'discovered_oper_status': ['2'], ...}},
+         {'check_plugin_name': 'if64', 'item': 'Fa1/0/1', 'parameters': {'discovered_oper_status': ['1'], ...}},
+         {'check_plugin_name': 'if64', 'item': 'Fa1/0/10', 'parameters': {'discovered_oper_status': ['2'], ...}},
+         {'check_plugin_name': 'if64', 'item': 'Fa1/0/11', 'parameters': {'discovered_oper_status': ['2'], ...}},
+         {'check_plugin_name': 'if64', 'item': 'Fa1/0/12', 'parameters': {'discovered_oper_status': ['1'], ...}}
+        ]
+
+        Args:
+            host:
+            debug:
+
+        Returns:
+
+        """
+        __autochecks_path = 'var/check_mk/autochecks'
+        autochecks_file = Path(f'{OMD_ROOT}/{__autochecks_path}/{host}.mk')
+        __data = []
+        if autochecks_file.exists():
+            data: List[Dict[str, str]] = literal_eval(autochecks_file.read_text())
+            for service in data:
+                if service['check_plugin_name'] in ['if64']:
+                    __data.append(service['item'])
+        else:
+            if debug:
+                print(f'Device: {host}: not found in auto checks path!')
+            return []
+
+        return __data
diff --git a/bin/topology_data/create_topology_data.py b/bin/topology_data/create_topology_data.py
index 86d43c523096a4ed0824958d67e3e3bf88b5b089..f0b3578d804aff1190495a703767ee845d536a52 100755
--- a/bin/topology_data/create_topology_data.py
+++ b/bin/topology_data/create_topology_data.py
@@ -34,6 +34,7 @@
 #             removed option --inventory-columns, now handled in CUSTOM_LAYERS
 #             removed option --path-in-inventory, now handled in CUSTOM_LAYERS
 #             removed lower limits for --keep and --min-age
+# 2023-1ß-29: fixed missing path from custom layer in host prefetch
 
 #
 # PoC for creating topology_data.json from inventory data
@@ -61,7 +62,7 @@ from create_topology_utils import (
     get_data_from_toml,
     merge_topologies,
     save_topology,
-    LQ_INTERFACES,
+    CACHE_INTERFACES_ITEM,
     PATH_INTERFACES,
     LAYERS,
 )
@@ -70,8 +71,9 @@ from create_topology_classes import (
     InventoryColumns,
     Settings,
     StaticConnection,
-    HostCache,
-    CacheSources,
+    HostCacheLiveStatus,
+    HostCacheFileSystem,
+    CacheItems,
 )
 
 HOST_MAP: Dict[str, str] = {}
@@ -89,7 +91,7 @@ def get_list_of_devices(data) -> List[str]:
 def get_service_by_interface(host: str, interface: str, debug: bool = False) -> str:
     # try to find the item for an interface
     def _match_entry_with_item(_entry: Dict[str, str]):
-        values = [_entry.get('name'), _entry.get('description'), entry.get('alias')]
+        values = [_entry.get('name'), _entry.get('description'), _entry.get('alias')]
         for value in values:
             if value in items:
                 return value
@@ -112,24 +114,24 @@ def get_service_by_interface(host: str, interface: str, debug: bool = False) ->
         return interface
 
     # get list of interface items
-    items = HOST_CACHE.get_data(host=host, source=CacheSources.lq, path=LQ_INTERFACES)
+    items = HOST_CACHE.get_data(host=host, item=CacheItems.interfaces, path=CACHE_INTERFACES_ITEM)
 
     # the easy case
     if interface in items:
         return interface
     else:
         # try to find the interface in the host interface inventory list
-        inventory = HOST_CACHE.get_data(host=host, source=CacheSources.inventory, path=PATH_INTERFACES)
+        inventory = HOST_CACHE.get_data(host=host, item=CacheItems.inventory, path=PATH_INTERFACES)
         if inventory:
-            for entry in inventory:
+            for _entry in inventory:
                 if interface in [
-                    entry.get('name'),
-                    entry.get('description'),
-                    entry.get('alias'),
-                    str(entry.get('index')),
-                    entry.get('phys_address'),
+                    _entry.get('name'),
+                    _entry.get('description'),
+                    _entry.get('alias'),
+                    str(_entry.get('index')),
+                    _entry.get('phys_address'),
                 ]:
-                    return _match_entry_with_item(entry)
+                    return _match_entry_with_item(_entry)
         if debug:
             print(f'Device: {host}: service for interface {interface} not found')
 
@@ -242,7 +244,7 @@ def create_topology(
                 continue
 
         # topo_data = get_inventory_data_lq(host=device, path=path_in_inventory, debug=debug)
-        topo_data = HOST_CACHE.get_data(host=device, source=CacheSources.inventory, path=path_in_inventory)
+        topo_data = HOST_CACHE.get_data(host=device, item=CacheItems.inventory, path=path_in_inventory)
         if topo_data:
             topology_data.update(
                 create_device_from_inv(
@@ -252,9 +254,9 @@ def create_topology(
                     label=label,
                 ))
             devices_list = get_list_of_devices(topology_data[device]['connections'])
-            for entry in devices_list:
-                if entry not in devices_done:
-                    devices_to_go.append(entry)
+            for _entry in devices_list:
+                if _entry not in devices_done:
+                    devices_to_go.append(_entry)
 
         devices_to_go = list(set(devices_to_go))
         devices_done.append(device)
@@ -270,7 +272,14 @@ def create_topology(
 if __name__ == '__main__':
     start_time = time_ns()
     SETTINGS = Settings(vars(parse_arguments()))
-    HOST_CACHE = HostCache()
+    match SETTINGS.backend:
+        case 'LIVESTATUS':
+            HOST_CACHE = HostCacheLiveStatus()
+        case 'FILESYSTEM':
+            HOST_CACHE = HostCacheFileSystem()
+        case _:
+            print(f'Backend {SETTINGS.backend} not (yet) implemented')
+            exit()
 
     print()
     print(f'Start time: {strftime(SETTINGS.time_format)}')
@@ -287,7 +296,7 @@ if __name__ == '__main__':
             jobs.append('STATIC')
         elif layer in LAYERS.keys():
             jobs.append(LAYERS[layer])
-            HOST_CACHE.add_inventory_prefetch_path(LAYERS[layer]['path'])
+            HOST_CACHE.add_inventory_prefetch_path(path=LAYERS[layer]['path'])
         elif layer == 'CUSTOM':
             for entry in CUSTOM_LAYERS:
                 jobs.append(entry)
diff --git a/bin/topology_data/create_topology_utils.py b/bin/topology_data/create_topology_utils.py
index cd0d0237d926a0ec31a1ce0645ffea0edb58d2db..a59bbdef80fc13a17c0be834d5401baf56cd4df6 100755
--- a/bin/topology_data/create_topology_utils.py
+++ b/bin/topology_data/create_topology_utils.py
@@ -39,15 +39,16 @@ LABEL_LLDP = 'inv_LLDP'
 COLUMNS_LLDP = 'system_name,local_port_num,port_id'
 COLUMNS_CDP = 'device_id,local_port,device_port'
 USER_DATA_FILE = 'create_topology_data.toml'
-LQ_INTERFACES = 'interface_items'
+CACHE_INTERFACES_ITEM = 'interface_items'
 LAYERS = {
     'CDP': {'path': PATH_CDP, 'columns': COLUMNS_CDP, 'label': LABEL_CDP},
     'LLDP': {'path': PATH_LLDP, 'columns': COLUMNS_LLDP, 'label': LABEL_LLDP},
 }
+OMD_ROOT = environ["OMD_ROOT"]
 
 
 def get_data_form_live_status(query: str):
-    address = f'{environ.get("OMD_ROOT")}/tmp/run/live'
+    address = f'{OMD_ROOT}/tmp/run/live'
     family = socket.AF_INET if type(address) is tuple else socket.AF_UNIX
     sock = socket.socket(family, socket.SOCK_STREAM)
     sock.connect(address)
@@ -84,7 +85,7 @@ def get_data_from_toml(file: str, debug: bool = False) -> Dict:
 
 def rm_tree(root: Path):
     # safety
-    if not str(root).startswith(f'{environ["OMD_ROOT"]}/var/topology_data'):
+    if not str(root).startswith(f'{OMD_ROOT}/var/topology_data'):
         print(f"WARNING: bad path to remove, {str(root)}, don\'t delete it.")
         return
     for p in root.iterdir():
@@ -300,22 +301,6 @@ def is_equal_with_default(data: Dict, file: str) -> bool:
         return compare_dicts(data, default_data)
 
 
-def get_inventory_data(host: str, debug: bool = False, ) -> Dict[str, str] | None:
-    query = f'GET hosts\nColumns: mk_inventory\nOutputFormat: python3\nFilter: host_name = {host}\n'
-    data = get_data_form_live_status(query=query)
-
-    if data:
-        try:
-            data = literal_eval(data[0][0].decode('utf-8'))
-        except SyntaxError as e:
-            if debug:
-                print(f'data: |{data}|')
-                print(f'type: {type(data)}')
-                print(f'exception: {e}')
-            return
-        return data
-
-
 def get_table_from_inventory(inventory: Dict[str, Any], path: List[str]) -> List | None:
     path = ('Nodes,' + ',Nodes,'.join(path.split(',')) + ',Table,Rows').split(',')
     table = inventory.copy()
@@ -325,21 +310,3 @@ def get_table_from_inventory(inventory: Dict[str, Any], path: List[str]) -> List
         except KeyError:
             return
     return table
-
-
-def get_interface_items_from_lq(host: str, debug: bool = False) -> List:
-    query = (
-        'GET services\n'
-        'Columns: host_name description check_command\n'
-        'Filter: description ~ Interface\n'
-        f'Filter: host_name = {host}\n'
-        'OutputFormat: python3\n'
-    )
-    data = get_data_form_live_status(query=query)
-    items = []
-    for host, description, check_command in data:
-        items.append(description[10:])  # remove 'Interface ' from description
-
-    if debug:
-        print(f'Interfaces items found: {len(items)} an host {host}')
-    return items
diff --git a/mkp/create_topology_data-0.2.0-20231116.mkp b/mkp/create_topology_data-0.2.0-20231116.mkp
new file mode 100644
index 0000000000000000000000000000000000000000..3dfb59c892d676c4d87023841ca96f214fbbc05a
Binary files /dev/null and b/mkp/create_topology_data-0.2.0-20231116.mkp differ
diff --git a/packages/create_topology_data b/packages/create_topology_data
index 1fc13fcdcf1cd90d7cd017347ec791d6cceb7ffd..49be6c70566befd421ec6179e058f50f5b6a76b8 100644
--- a/packages/create_topology_data
+++ b/packages/create_topology_data
@@ -1,6 +1,5 @@
 {'author': 'Th.L. (thl-cmk[at]outlook[dot]com)',
- 'description': 'PoC for Network Visualization data creation from inventory '
-                'data\n'
+ 'description': 'Network Visualization data creation tool from inventory data\n'
                 '\n'
                 'This tool creates the topology data file needed for the '
                 'Checkmk "Network Visualization" plugin \n'
@@ -34,6 +33,9 @@
                 'LLDP: '
                 'https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/inventory/inv_lldp_cache\n'
                 '\n'
+                'For the latest version and documentation see:\n'
+                'https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/create_topology_data\n'
+                '\n'
                 '#########################################################################\n'
                 'Important:\n'
                 '\n'
@@ -57,7 +59,7 @@
                    'topology_data/create_topology_args.py']},
  'name': 'create_topology_data',
  'title': 'Network Visualization data creation',
- 'version': '0.1.0-20231028',
+ 'version': '0.2.0-20231116',
  'version.min_required': '2.2.0p1',
  'version.packaged': '2.2.0p11',
  'version.usable_until': '2.3.0p1'}