diff -r 41f98de1e8b3 -r 43a8edb5b671 src/org/openbravo/dal/security/OrganizationStructureProvider.java
--- a/src/org/openbravo/dal/security/OrganizationStructureProvider.java	Thu Nov 21 15:41:54 2019 +0100
+++ b/src/org/openbravo/dal/security/OrganizationStructureProvider.java	Thu Nov 21 18:41:42 2019 +0100
@@ -28,6 +28,8 @@
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -55,6 +57,8 @@
 public class OrganizationStructureProvider implements OBNotSingleton {
   final static Logger log = LogManager.getLogger();
 
+  final static ConcurrentMap<String, Map<String, OrgNode>> nodeStructureByClient = new ConcurrentHashMap<String, Map<String, OrgNode>>();
+  
   private boolean isInitialized = false;
   private Map<String, OrgNode> orgNodes;
   private String clientId;
@@ -78,31 +82,36 @@
       setClientId(OBContext.getOBContext().getCurrentClient().getId());
     }
 
-    // Read all org tree of any client: bypass DAL to prevent security checks and Hibernate to make
-    // it in a single query. Using direct SQL managed by Hibernate as in this point SQLC is not
-    // allowed because this code is used while generating entities.
-    String sql = "select n.node_id, n.parent_id, o.isready, ot.islegalentity, ot.isbusinessunit, ot.istransactionsallowed, o.isperiodcontrolallowed"
-        + "  from ad_tree t, ad_treenode n, ad_org o, ad_orgtype ot"
-        + " where n.node_id = o.ad_org_id" + "   and o.ad_orgtype_id = ot.ad_orgtype_id"
-        + "   and n.ad_tree_id = t.ad_tree_id" + "   and t.ad_table_id = '155'"
-        + "   and t.ad_client_id = :clientId";
-
-    @SuppressWarnings("rawtypes")
-    NativeQuery qry = OBDal.getInstance().getSession().createNativeQuery(sql);
-    qry.setParameter("clientId", getClientId());
-
-    @SuppressWarnings("unchecked")
-    List<Object[]> treeNodes = qry.list();
-
-    orgNodes = new HashMap<>(treeNodes.size());
-    for (Object[] nodeDef : treeNodes) {
-      final OrgNode on = new OrgNode(nodeDef);
-      String nodeId = (String) nodeDef[0];
-      orgNodes.put(nodeId, on);
-    }
-
-    for (Entry<String, OrgNode> nodeEntry : orgNodes.entrySet()) {
-      nodeEntry.getValue().resolve(nodeEntry.getKey());
+    if (nodeStructureByClient.containsKey(getClientId())) {
+      orgNodes = nodeStructureByClient.get(getClientId());
+    } else {
+      // Read all org tree of any client: bypass DAL to prevent security checks and Hibernate to make
+      // it in a single query. Using direct SQL managed by Hibernate as in this point SQLC is not
+      // allowed because this code is used while generating entities.
+      String sql = "select n.node_id, n.parent_id, o.isready, ot.islegalentity, ot.isbusinessunit, ot.istransactionsallowed, o.isperiodcontrolallowed"
+          + "  from ad_tree t, ad_treenode n, ad_org o, ad_orgtype ot"
+          + " where n.node_id = o.ad_org_id" + "   and o.ad_orgtype_id = ot.ad_orgtype_id"
+          + "   and n.ad_tree_id = t.ad_tree_id" + "   and t.ad_table_id = '155'"
+          + "   and t.ad_client_id = :clientId";
+  
+      @SuppressWarnings("rawtypes")
+      NativeQuery qry = OBDal.getInstance().getSession().createNativeQuery(sql);
+      qry.setParameter("clientId", getClientId());
+  
+      @SuppressWarnings("unchecked")
+      List<Object[]> treeNodes = qry.list();
+      
+      orgNodes = new HashMap<>(treeNodes.size());
+      for (Object[] nodeDef : treeNodes) {
+        final OrgNode on = new OrgNode(nodeDef);
+        String nodeId = (String) nodeDef[0];
+        orgNodes.put(nodeId, on);
+      }
+  
+      for (Entry<String, OrgNode> nodeEntry : orgNodes.entrySet()) {
+        nodeEntry.getValue().resolve(nodeEntry.getKey());
+      }
+      nodeStructureByClient.putIfAbsent(getClientId(), orgNodes);
     }
 
     log.debug("Client {} initialized in {} ms", getClientId(),
@@ -458,6 +467,10 @@
     }
     return trxAllowedOrgs;
   }
+  
+  public static void clearOrgStructureCache() {
+    nodeStructureByClient.clear();
+  }
 
   private class OrgNode {
     private String parentNodeId;
diff -r 41f98de1e8b3 -r 43a8edb5b671 src/org/openbravo/dal/security/OrganizationsChangedEvent.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/openbravo/dal/security/OrganizationsChangedEvent.java	Thu Nov 21 18:41:42 2019 +0100
@@ -0,0 +1,62 @@
+package org.openbravo.dal.security;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.model.Property;
+import org.openbravo.client.kernel.event.EntityDeleteEvent;
+import org.openbravo.client.kernel.event.EntityNewEvent;
+import org.openbravo.client.kernel.event.EntityPersistenceEventObserver;
+import org.openbravo.client.kernel.event.EntityUpdateEvent;
+import org.openbravo.model.common.enterprise.Organization;
+
+@ApplicationScoped
+public class OrganizationsChangedEvent extends EntityPersistenceEventObserver {
+
+  private static Entity[] entities = { ModelProvider.getInstance().getEntity(Organization.ENTITY_NAME)};
+  private static Property[] properties = { 
+      ModelProvider.getInstance().getEntity(Organization.ENTITY_NAME).getProperty(Organization.PROPERTY_PERIODCONTROLALLOWEDORGANIZATION),
+      ModelProvider.getInstance().getEntity(Organization.ENTITY_NAME).getProperty(Organization.PROPERTY_CALENDAROWNERORGANIZATION),
+      ModelProvider.getInstance().getEntity(Organization.ENTITY_NAME).getProperty(Organization.PROPERTY_LEGALENTITYORGANIZATION),
+      ModelProvider.getInstance().getEntity(Organization.ENTITY_NAME).getProperty(Organization.PROPERTY_BUSINESSUNITORGANIZATION)
+      };
+
+  @Override
+  protected Entity[] getObservedEntities() {
+    return entities;
+  }
+
+  public void onUpdate(@Observes EntityUpdateEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    Organization oldValue;
+    Organization newValue;
+    for (Property property: properties) {
+      oldValue = (Organization) (event.getPreviousState(property));
+      newValue = (Organization) (event.getCurrentState(property));
+      if (((oldValue == null) != (newValue == null))
+          || (oldValue != null && !oldValue.getId().equals(newValue.getId()))) {
+        OrganizationStructureProvider.clearOrgStructureCache();
+        return;
+      }
+    }
+  }
+
+  public void onSave(@Observes EntityNewEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    OrganizationStructureProvider.clearOrgStructureCache();
+  }
+
+  public void onDelete(@Observes EntityDeleteEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    OrganizationStructureProvider.clearOrgStructureCache();
+  }
+
+}
