private void updateBBoxCache() throws FeatureStoreException {

    // beware of concurrent transactions
    synchronized (fs) {
      Set<QName> recalcFTs = bboxTracker.getRecalcFeatureTypes();
      Map<QName, Envelope> ftNamesToIncreaseBBoxes = bboxTracker.getIncreaseBBoxes();

      // handle bbox increases
      for (Entry<QName, Envelope> ftNameToIncreaseBBox : ftNamesToIncreaseBBoxes.entrySet()) {
        QName ftName = ftNameToIncreaseBBox.getKey();
        Envelope bbox = null;
        if (fs.getBBoxCache().contains(ftName)) {
          bbox = ftNameToIncreaseBBox.getValue();
        }
        if (bbox != null) {
          Envelope oldBbox = fs.getBBoxCache().get(ftName);
          if (oldBbox != null) {
            bbox = oldBbox.merge(bbox);
          }
          fs.getBBoxCache().set(ftName, bbox);
        }
      }

      // TODO configuration switch for bbox recalculation strategy
      if (!recalcFTs.isEmpty()) {
        LOG.debug(
            "Full recalculation of feature type envelopes required. Delete 'bbox_cache.properties' if you need minimal envelopes.");
      }

      try {
        fs.getBBoxCache().persist();
      } catch (Throwable t) {
        LOG.error("Unable to persist bbox cache: " + t.getMessage());
      }
    }
  }