diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
index 6f2e6f0816d8cd72ff49ff5ffc835ad4df84e088..417239c99db58a48c3b1ed7357115cddebdb78bc 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
@@ -98,6 +98,11 @@
 import org.sleuthkit.autopsy.casemodule.events.PersonsUpdatedEvent;
 import org.sleuthkit.autopsy.casemodule.events.PersonsDeletedEvent;
 import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent;
+import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesAddedEvent;
+import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesDeletedEvent;
+import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesUpdatedEvent;
+import org.sleuthkit.autopsy.casemodule.events.TagSetsEvent.TagSetsAddedEvent;
+import org.sleuthkit.autopsy.casemodule.events.TagSetsEvent.TagSetsDeletedEvent;
 import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData.CaseNodeDataException;
 import org.sleuthkit.autopsy.casemodule.multiusercases.CoordinationServiceUtils;
 import org.sleuthkit.autopsy.casemodule.services.Services;
@@ -484,7 +489,32 @@ public enum Events {
         /**
          * One or more hosts have been removed from a person.
          */
-        HOSTS_REMOVED_FROM_PERSON;
+        HOSTS_REMOVED_FROM_PERSON,
+        
+        /**
+         * One or more TagNames have been added.
+         */
+        TAG_NAMES_ADDED,
+        
+        /**
+         * One or more TagNames have been updated.
+         */
+        TAG_NAMES_UPDATED,
+        
+        /**
+         * One or more TagNames have been deleted.
+         */
+        TAG_NAMES_DELETED,
+        
+        /**
+         * One or more TagSets have been added.
+         */
+        TAG_SETS_ADDED,
+        
+        /**
+         * One or more TagSets have been removed.
+         */
+        TAG_SETS_DELETED;
 
     };
 
@@ -627,7 +657,31 @@ public void publishHostsAddedToPersonEvent(TskEvent.HostsAddedToPersonTskEvent e
         public void publisHostsRemovedFromPersonEvent(TskEvent.HostsRemovedFromPersonTskEvent event) {
             eventPublisher.publish(new HostsRemovedFromPersonEvent(event.getPerson(), event.getHostIds()));
         }
+        
+        @Subscribe
+        public void publicTagNamesAdded(TskEvent.TagNamesAddedTskEvent event) {
+            eventPublisher.publish(new TagNamesAddedEvent(event.getTagNames()));
+        }
+
+        @Subscribe
+        public void publicTagNamesUpdated(TskEvent.TagNamesUpdatedTskEvent event) {
+            eventPublisher.publish(new TagNamesUpdatedEvent(event.getTagNames()));
+        }
+
+        @Subscribe
+        public void publicTagNamesDeleted(TskEvent.TagNamesDeletedTskEvent event) {
+            eventPublisher.publish(new TagNamesDeletedEvent(event.getTagNameIds()));
+        }
 
+        @Subscribe
+        public void publicTagSetsAdded(TskEvent.TagSetsAddedTskEvent event) {
+            eventPublisher.publish(new TagSetsAddedEvent(event.getTagSets()));
+        }
+
+        @Subscribe
+        public void publicTagSetsDeleted(TskEvent.TagSetsDeletedTskEvent event) {
+            eventPublisher.publish(new TagSetsDeletedEvent(event.getTagSetIds()));
+        }
     }
 
     /**
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..60ac94ff234aeb29f04c4e2b5ff7c50d8cff6a2f
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java
@@ -0,0 +1,126 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2021 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.casemodule.events;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.datamodel.TagName;
+import org.sleuthkit.datamodel.TaggingManager;
+import org.sleuthkit.datamodel.TskCoreException;
+
+/**
+ * A base class for TagName added and update events.
+ */
+public class TagNamesEvent extends TskDataModelChangedEvent<TagName, TagName> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Construct the base event for TagNames that have been added or updated.
+     *
+     * @param eventName The name of the event.
+     * @param tagNames  The TagNames that have been modified.
+     */
+    private TagNamesEvent(String eventName, List<TagName> tagNames) {
+        super(eventName, null, null, tagNames, TagName::getId);
+    }
+
+    /**
+     * Returns a list of the added or modified TagNames.
+     * 
+     * @return The event list of TagNames.
+     */
+    public List<TagName> getTagNames() {
+        return getNewValue();
+    }
+
+    @Override
+    protected List<TagName> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
+        List<TagName> tagNames = new ArrayList<>();
+        TaggingManager taggingMrg = caseDb.getTaggingManager();
+        for (Long id : ids) {
+            tagNames.add(taggingMrg.getTagName(id));
+        }
+
+        return tagNames;
+    }
+
+    /**
+     * Application events published when TagNames have been Added from the
+     * Sleuth Kit data model for a case.
+     */
+    public static class TagNamesAddedEvent extends TagNamesEvent {
+
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * Construct an application event published when TagNames have been
+         * added to the Sleuth Kit data model.
+         *
+         * @param tagNames The TagNames that have been added.
+         */
+        public TagNamesAddedEvent(List<TagName> tagNames) {
+            super(Case.Events.TAG_NAMES_ADDED.name(), tagNames);
+        }
+    }
+
+    /**
+     * Application events published when TagNames have been updated from the
+     * Sleuth Kit data model for a case.
+     */
+    public static class TagNamesUpdatedEvent extends TagNamesEvent {
+
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * Construct an application event published when TagNames have been
+         * updated in the Sleuth Kit data model.
+         *
+         * @param tagNames The TagNames that have been updated.
+         */
+        public TagNamesUpdatedEvent(List<TagName> tagNames) {
+            super(Case.Events.TAG_NAMES_UPDATED.name(), tagNames);
+        }
+    }
+
+    /**
+     * Application events published when TagNames have been deleted from the
+     * Sleuth Kit data model for a case.
+     */
+    public static class TagNamesDeletedEvent extends TskDataModelObjectsDeletedEvent {
+
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * Constructs an application event published when the TagNames have been
+         * deleted from the Sleuth Kit data model for a case.
+         *
+         * @param tagNameIds The IDs of the TagNames that have been deleted.
+         */
+        public TagNamesDeletedEvent(List<Long> tagNameIds) {
+            super(Case.Events.TAG_NAMES_DELETED.name(), tagNameIds);
+        }
+        
+        public List<Long> getTagNameIds() {
+            return getOldValue();
+        }
+    }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..0896241e7d335c37b5596a65027fddffa906446c
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java
@@ -0,0 +1,103 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2021 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.casemodule.events;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.datamodel.TagSet;
+import org.sleuthkit.datamodel.TaggingManager;
+import org.sleuthkit.datamodel.TskCoreException;
+
+/**
+ * A base class for TagSet added and update events.
+ */
+public class TagSetsEvent extends TskDataModelChangedEvent<TagSet, TagSet> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new TagSetEvent.
+     *
+     * @param eventName
+     * @param tagSets
+     */
+    private TagSetsEvent(String eventName, List<TagSet> tagSets) {
+        super(eventName, null, null, tagSets, TagSet::getId);
+    }
+
+    /**
+     * Returns a list of the TagSet objects that were added or modified for this
+     * event.
+     *
+     * @return A list of TagSet objects.
+     */
+    public List<TagSet> getTagSets() {
+        return this.getNewValue();
+    }
+
+    @Override
+    protected List<TagSet> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
+        List<TagSet> tagSets = new ArrayList<>();
+        TaggingManager taggingMrg = caseDb.getTaggingManager();
+        for (Long id : ids) {
+            tagSets.add(taggingMrg.getTagSet(id));
+        }
+        return tagSets;
+    }
+
+    /**
+     * Application events published when TagSets have been Added from the Sleuth
+     * Kit data model for a case.
+     */
+    public static class TagSetsAddedEvent extends TagSetsEvent {
+
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * Construct an application event published when TagSetss have been
+         * added to the Sleuth Kit data model.
+         *
+         * @param tagSets The TagSets that have been added.
+         */
+        public TagSetsAddedEvent(List<TagSet> tagSets) {
+            super(Case.Events.TAG_SETS_ADDED.name(), tagSets);
+        }
+    }
+
+    /**
+     * Application events published when TagSets have been deleted from the
+     * Sleuth Kit data model for a case.
+     */
+    public static class TagSetsDeletedEvent extends TskDataModelObjectsDeletedEvent {
+
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * Constructs an application event published when the TagSets have been
+         * deleted from the Sleuth Kit data model for a case.
+         *
+         * @param tagNameIds The IDs of the TagNames that have been deleted.
+         */
+        public TagSetsDeletedEvent(List<Long> tagNameIds) {
+            super(Case.Events.TAG_SETS_DELETED.name(), tagNameIds);
+        }
+    }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java
index ff07662e64971d48c42133372c763a3b31cf4873..f3645fd7c6443c06183277b2b5693a335f8e4c1d 100755
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java
@@ -236,7 +236,7 @@ private String toSettingsFormat() {
     TagName saveToCase(SleuthkitCase caseDb) {
         TagName tagName = null;
         try {
-            tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus);
+            tagName = caseDb.getTaggingManager().addOrUpdateTagName(displayName, description, color, knownStatus);
         } catch (TskCoreException ex) {
             LOGGER.log(Level.SEVERE, "Error saving tag name definition", ex);
         }
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
index 4bb813a779af2ef9f1e3e7aa9c94d1f9591294e7..a4bd51bcce6b11d8e6e031d5e406acde2ed842cc 100755
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
@@ -18,9 +18,12 @@
  */
 package org.sleuthkit.autopsy.casemodule.services;
 
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -29,8 +32,11 @@
 import java.util.Set;
 import java.util.logging.Level;
 import org.openide.util.NbBundle;
+import org.openide.util.WeakListeners;
 import org.sleuthkit.autopsy.casemodule.Case;
 import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
+import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent;
+import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesDeletedEvent;
 import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager;
 import org.sleuthkit.autopsy.coreutils.Logger;
 import org.sleuthkit.datamodel.BlackboardArtifact;
@@ -60,6 +66,37 @@ public class TagsManager implements Closeable {
     private static String PROJECT_VIC_TAG_SET_NAME = "Project VIC";
 
     private static final Object lock = new Object();
+    
+    private final Map<String, TagName> allTagNameMap = Collections.synchronizedMap(new HashMap<>());
+    
+    private final PropertyChangeListener listener = new PropertyChangeListener() {
+        @Override
+        public void propertyChange(PropertyChangeEvent evt) {
+            if (evt.getPropertyName().equals(Case.Events.TAG_NAMES_ADDED.name())
+                    || evt.getPropertyName().equals(Case.Events.TAG_NAMES_UPDATED.name())) {
+                TagNamesEvent tagEvent = (TagNamesEvent) evt;
+                List<TagName> addTagNames = tagEvent.getTagNames();
+                for (TagName tag : addTagNames) {
+                    allTagNameMap.put(tag.getDisplayName(), tag);
+                }
+            } else if (evt.getPropertyName().equals(Case.Events.TAG_NAMES_DELETED.name())) {
+                TagNamesDeletedEvent tagEvent = (TagNamesDeletedEvent) evt;
+                List<Long> deletedIds = tagEvent.getTagNameIds();
+                List<String> keysToRemove = new ArrayList<>();
+                for (TagName tagName : getAllTagNames()) {
+                    if (deletedIds.contains(tagName.getId())) {
+                        keysToRemove.add(tagName.getDisplayName());
+                    }
+                }
+
+                for (String key : keysToRemove) {
+                    allTagNameMap.remove(key);
+                }
+            }
+        }
+    };
+    
+    private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null);
 
     static {
 
@@ -177,8 +214,6 @@ public static List<String> getNotableTagDisplayNames() {
             /*
              * No current case, nothing more to add to the set.
              */
-        } catch (TskCoreException ex) {
-            LOGGER.log(Level.SEVERE, "Failed to get list of TagNames from TagsManager.", ex);
         }
         return tagDisplayNames;
     }
@@ -268,21 +303,26 @@ public static void addTagSetDefinition(TagSetDefinition tagSetDef) throws IOExce
                 
                 // add the standard tag names
                 for (TagNameDefinition def : TagNameDefinition.getStandardTagNameDefinitions()) {
-                    caseDb.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus());
+                    taggingMgr.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus());
                 }
                 
                 //Assume new case and add all tag sets
                 for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) {
                     List<TagName> tagNamesInSet = new ArrayList<>();
                     for (TagNameDefinition tagNameDef : setDef.getTagNameDefinitions()) {
-                        tagNamesInSet.add(caseDb.addOrUpdateTagName(tagNameDef.getDisplayName(), tagNameDef.getDescription(), tagNameDef.getColor(), tagNameDef.getKnownStatus()));
+                        tagNamesInSet.add(taggingMgr.addOrUpdateTagName(tagNameDef.getDisplayName(), tagNameDef.getDescription(), tagNameDef.getColor(), tagNameDef.getKnownStatus()));
                     }
 
                     if (!tagNamesInSet.isEmpty()) {
                         taggingMgr.addTagSet(setDef.getName(), tagNamesInSet);
                     }
                 }
+            }         
+
+            for(TagName tagName: caseDb.getAllTagNames()) {
+                allTagNameMap.put(tagName.getDisplayName(), tagName);
             }
+            
         } catch (TskCoreException ex) {
             LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex);
         } catch (IOException ex) {
@@ -292,6 +332,10 @@ public static void addTagSetDefinition(TagSetDefinition tagSetDef) throws IOExce
         for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) {
             tagName.saveToCase(caseDb);
         }
+        
+        Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_UPDATED), weakListener);
+        Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_ADDED), weakListener);
+        Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_DELETED), weakListener);
     }
 
     /**
@@ -337,11 +381,12 @@ public TagSet addTagSet(String name, List<TagName> tagNameList) throws TskCoreEx
      * Gets a list of all tag names currently in the case database.
      *
      * @return A list, possibly empty, of TagName objects.
-     *
-     * @throws TskCoreException If there is an error querying the case database.
      */
-    public List<TagName> getAllTagNames() throws TskCoreException {
-        return caseDb.getAllTagNames();
+    public synchronized List<TagName> getAllTagNames() {
+        
+        List<TagName> tagNames = new ArrayList<>();
+        tagNames.addAll(allTagNameMap.values());
+        return tagNames;
     }
 
     /**
@@ -439,7 +484,7 @@ public List<TagName> getTagNamesInUseForUser(long dsObjId, String userName) thro
      */
     public Map<String, TagName> getDisplayNamesToTagNamesMap() throws TskCoreException {
         Map<String, TagName> tagNames = new HashMap<>();
-        for (TagName tagName : caseDb.getAllTagNames()) {
+        for (TagName tagName : getAllTagNames()) {
             tagNames.put(tagName.getDisplayName(), tagName);
         }
         return tagNames;
@@ -521,13 +566,13 @@ public TagName addTagName(String displayName, String description, TagName.HTML_C
     public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException {
         synchronized (lock) {
             try {
-                TagName tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus);
+                TagName tagName = caseDb.getTaggingManager().addOrUpdateTagName(displayName, description, color, knownStatus);
                 Set<TagNameDefinition> customTypes = TagNameDefinition.getTagNameDefinitions();
                 customTypes.add(new TagNameDefinition(displayName, description, color, knownStatus));
                 TagNameDefinition.setTagNameDefinitions(customTypes);
                 return tagName;
             } catch (TskCoreException ex) {
-                List<TagName> existingTagNames = caseDb.getAllTagNames();
+                List<TagName> existingTagNames = getAllTagNames();
                 for (TagName tagName : existingTagNames) {
                     if (tagName.getDisplayName().equals(displayName)) {
                         throw new TagNameAlreadyExistsException();
@@ -1039,5 +1084,4 @@ public boolean tagNameExists(String tagDisplayName) {
     @Override
     public void close() throws IOException {
     }
-
 }
diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java
index 3efcd5125018e633d787f668e4c3d2098ea6479b..f18f05f61fdf206ca033a975ddebcab17fa8fd19 100644
--- a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java
+++ b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java
@@ -340,7 +340,7 @@ public void generateReport(String reportPath, PortableCaseReportModuleSettings o
         progressPanel.updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingTags());
         try {
             for (TagName tagName : tagNames) {
-                TagName newTagName = portableSkCase.addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
+                TagName newTagName = portableSkCase.getTaggingManager().addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
                 oldTagNameToNewTagName.put(tagName, newTagName);
             }
         } catch (TskCoreException ex) {
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java
index 4a8664eb6f7250c9ff49293217b19302bba511f0..897b50ae2bc52cd913419d14440cfe5384fbebb6 100755
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java
@@ -149,7 +149,7 @@ public void closeCaseResources(CaseContext context) throws AutopsyServiceExcepti
     private void addProjetVicTagSet(Case currentCase) throws TskCoreException {
         List<TagName> tagNames = new ArrayList<>();
         for (TagNameDefinition def : PROJECT_VIC_US_CATEGORIES) {
-            tagNames.add(currentCase.getSleuthkitCase().addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()));
+            tagNames.add(currentCase.getSleuthkitCase().getTaggingManager().addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()));
         }
         currentCase.getServices().getTagsManager().addTagSet(PROJECT_VIC_TAG_SET_NAME, tagNames);
     }