diff --git a/tangostationcontrol/tangostationcontrol/clients/opcua_client.py b/tangostationcontrol/tangostationcontrol/clients/opcua_client.py
index ce4447de3b9c8339bd36cc1e75a04ec6867b04de..f0c246a691ea163a7549715bee5d15393cc6674d 100644
--- a/tangostationcontrol/tangostationcontrol/clients/opcua_client.py
+++ b/tangostationcontrol/tangostationcontrol/clients/opcua_client.py
@@ -58,6 +58,9 @@ class OPCUAConnection(AsyncCommClient):
         # prefix path to all nodes with this. this allows the user to switch trees more easily.
         self.node_path_prefix = []
 
+        # cache of looked up child node lists for each comma-separated parent path
+        self._node_cache = {}
+
         super().__init__(fault_func, event_loop)
 
     def _servername(self):
@@ -130,13 +133,41 @@ class OPCUAConnection(AsyncCommClient):
 
         return path
 
+    async def get_node(self, path):
+        """ Retrieve an OPC-UA node from either the cache, or the server. """
+
+        if not path:
+            return self.obj
+
+        cache_key = ",".join(path)
+
+        # lookup in cache
+        if cache_key in self._node_cache:
+            return self._node_cache[cache_key]
+
+        # cache it and all of its siblings to save us the round trips for them later on.
+        parent_path = path[:-1]
+        parent_node = await self.obj.get_child(parent_path) if parent_path else self.obj
+        child_nodes = await parent_node.get_children_descriptions()
+
+        for child_node in child_nodes:
+            # add node to the cache
+            child_path = parent_path + [f"{self.name_space_index}:{child_node.DisplayName.Text}"]
+            self._node_cache[",".join(child_path)] = self.client.get_node(child_node.NodeId)
+
+        # lookup in cache again. if the name is valid, it should be in there.
+        if cache_key in self._node_cache:
+            return self._node_cache[cache_key]
+
+        # we couldnt find the requested child, ask server directly to get the appropriate error
+        return await self.obj.get_child(path)
 
     async def setup_protocol_attribute(self, annotation, attribute):
         # process the annotation
         path = self.get_node_path(annotation)
 
         try:
-            node = await self.obj.get_child(path)
+            node = await self.get_node(path)
         except Exception as e:
             logger.exception("Could not get node: %s on server %s", path, self._servername())
             raise Exception("Could not get node: %s on server %s", path, self._servername()) from e
@@ -180,7 +211,7 @@ class OPCUAConnection(AsyncCommClient):
 
         try:
             # call method in its parent node
-            node = await self.obj.get_child(method_path[:-1]) if len(method_path) > 1 else self.obj
+            node = await self.get_node(method_path[:-1])
             result = await node.call_method(method_path[-1], *args)
         except Exception as e:
             raise Exception(f"Calling method {method_path} failed") from e
diff --git a/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py
index c1c29ee04279bab3c943ccc35d4e3a5071345607..25968deded93d8d45160c5a1949521784ab59e7a 100644
--- a/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py
+++ b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py
@@ -86,6 +86,7 @@ class TestOPCua(base.AsyncTestCase):
         m_opc_client_members.send_hello = asynctest.asynctest.CoroutineMock()
         m_objects_node = asynctest.Mock()
         m_objects_node.get_child = asynctest.asynctest.CoroutineMock()
+        m_objects_node.get_children_descriptions = asynctest.asynctest.CoroutineMock()
         m_opc_client_members.get_objects_node = asynctest.Mock(return_value=m_objects_node)
         m_opc_client.return_value = m_opc_client_members
 
@@ -108,7 +109,7 @@ class TestOPCua(base.AsyncTestCase):
                 m_attribute = mock_attr(i.numpy_type, dim_x, dim_y)
 
                 # pretend like there is a running OPCua server with a node that has this name
-                m_annotation = ["2:PCC", f"2:testNode_{str(i.numpy_type)}_{str(dim_x)}_{str(dim_y)}"]
+                m_annotation = [f"2:testNode_{str(i.numpy_type)}_{str(dim_x)}_{str(dim_y)}"]
 
                 test_client = OPCUAConnection("opc.tcp://localhost:4874/freeopcua/server/", "http://lofar.eu", 5, mock.Mock(), self.loop)
                 try: