diff --git a/Essentials/src/main/java/com/earth2me/essentials/EssentialsUpgrade.java b/Essentials/src/main/java/com/earth2me/essentials/EssentialsUpgrade.java
index 9c47154a1..5511967cf 100644
--- a/Essentials/src/main/java/com/earth2me/essentials/EssentialsUpgrade.java
+++ b/Essentials/src/main/java/com/earth2me/essentials/EssentialsUpgrade.java
@@ -438,7 +438,7 @@ public class EssentialsUpgrade {
 
     public void convertKits() {
         final Kits kits = ess.getKits();
-        final EssentialsConfiguration config = kits.getConfig();
+        final EssentialsConfiguration config = kits.getRootConfig();
         if (doneFile.getBoolean("kitsyml", false)) {
             return;
         }
diff --git a/Essentials/src/main/java/com/earth2me/essentials/Kits.java b/Essentials/src/main/java/com/earth2me/essentials/Kits.java
index 9d8c4639a..40f40843d 100644
--- a/Essentials/src/main/java/com/earth2me/essentials/Kits.java
+++ b/Essentials/src/main/java/com/earth2me/essentials/Kits.java
@@ -4,84 +4,106 @@ import com.earth2me.essentials.config.ConfigurateUtil;
 import com.earth2me.essentials.config.EssentialsConfiguration;
 import com.earth2me.essentials.utils.NumberUtil;
 import org.spongepowered.configurate.CommentedConfigurationNode;
-import org.spongepowered.configurate.serialize.SerializationException;
 
 import java.io.File;
 import java.math.BigDecimal;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 import static com.earth2me.essentials.I18n.capitalCase;
 import static com.earth2me.essentials.I18n.tl;
 
 public class Kits implements IConf {
-    private final EssentialsConfiguration config;
-    private CommentedConfigurationNode kits;
+    private final IEssentials ess;
+    private final EssentialsConfiguration rootConfig;
+    private final Map<String, EssentialsConfiguration> kitToConfigMap = new HashMap<>();
+    private final Map<String, Map<String, Object>> kitMap = new HashMap<>();
 
     public Kits(final IEssentials essentials) {
-        config = new EssentialsConfiguration(new File(essentials.getDataFolder(), "kits.yml"), "/kits.yml");
+        this.ess = essentials;
+        this.rootConfig = new EssentialsConfiguration(new File(essentials.getDataFolder(), "kits.yml"), "/kits.yml");
 
         reloadConfig();
     }
 
     @Override
     public void reloadConfig() {
-        config.load();
-        kits = _getKits();
+        rootConfig.load();
+        parseKits();
     }
 
     public File getFile() {
-        return config.getFile();
+        return rootConfig.getFile();
     }
 
-    private CommentedConfigurationNode _getKits() {
-        final CommentedConfigurationNode section = config.getSection("kits");
-        if (section != null) {
-            final CommentedConfigurationNode newSection = config.newSection();
-            for (final String kitItem : ConfigurateUtil.getKeys(section)) {
-                final CommentedConfigurationNode kitSection = section.node(kitItem);
-                if (kitSection.isMap()) {
-                    try {
-                        newSection.node(kitItem.toLowerCase(Locale.ENGLISH)).set(kitSection);
-                    } catch (SerializationException e) {
-                        e.printStackTrace();
+    private void parseKit(final String kitName, final CommentedConfigurationNode kitSection, final EssentialsConfiguration parentConfig) {
+        if (kitSection.isMap()) {
+            final String effectiveKitName = kitName.toLowerCase(Locale.ENGLISH);
+            kitToConfigMap.put(effectiveKitName, parentConfig);
+            kitMap.put(effectiveKitName, ConfigurateUtil.getRawMap(kitSection));
+        }
+    }
+
+    private void parseKits() {
+        kitToConfigMap.clear();
+        kitMap.clear();
+
+        // Kits from kits.yml file
+        final CommentedConfigurationNode fileKits = rootConfig.getSection("kits");
+        if (fileKits != null) {
+            for (final Map.Entry<String, CommentedConfigurationNode> kitEntry : ConfigurateUtil.getMap(fileKits).entrySet()) {
+                parseKit(kitEntry.getKey(), kitEntry.getValue(), rootConfig);
+            }
+        }
+
+        // Kits from kits subdirectory
+        final File kitsFolder = new File(this.ess.getDataFolder(), "kits");
+        if (!kitsFolder.exists() || !kitsFolder.isDirectory()) {
+            return;
+        }
+
+        final File[] kitsFiles = kitsFolder.listFiles();
+
+        //noinspection ConstantConditions - will not be null, conditions checked above.
+        for (final File kitFile : kitsFiles) {
+            if (kitFile.getName().endsWith(".yml")) {
+                final EssentialsConfiguration kitConfig = new EssentialsConfiguration(kitFile);
+                kitConfig.load();
+                final CommentedConfigurationNode kits = kitConfig.getSection("kits");
+                if (kits != null) {
+                    for (final Map.Entry<String, CommentedConfigurationNode> kitEntry : ConfigurateUtil.getMap(kits).entrySet()) {
+                        parseKit(kitEntry.getKey(), kitEntry.getValue(), kitConfig);
                     }
                 }
             }
-            return newSection;
         }
-        return null;
     }
 
-    public EssentialsConfiguration getConfig() {
-        return config;
+    /**
+     * Should be used for EssentialsUpgrade conversions <b>only</b>.
+     */
+    public EssentialsConfiguration getRootConfig() {
+        return rootConfig;
     }
 
-    public CommentedConfigurationNode getKits() {
-        return kits;
+    public Set<String> getKitKeys() {
+        return kitMap.keySet();
     }
 
-    public Map<String, Object> getKit(String name) {
-        name = name.replace('.', '_').replace('/', '_');
-        if (getKits() != null) {
-            final CommentedConfigurationNode kits = getKits();
-            // Other parts of the codebase/3rd party plugins expect us to lowercase kit names here.
-            // This isn't strictly needed for the future of Essentials, but for compatibility it's here.
-            final CommentedConfigurationNode kitSection = kits.node(name.toLowerCase());
-            if (!kitSection.virtual() && kitSection.isMap()) {
-                return ConfigurateUtil.getRawMap(kitSection);
-            }
+    public Map<String, Object> getKit(final String name) {
+        if (name != null) {
+            return kitMap.get(name.replace('.', '_').replace('/', '_'));
         }
-
         return null;
     }
 
     // Tries to find an existing kit name that matches the given name, ignoring case. Returns null if no match.
     public String matchKit(final String name) {
-        final CommentedConfigurationNode section = config.getSection("kits");
-        if (section != null) {
-            for (final String kitName : ConfigurateUtil.getKeys(section)) {
+        if (name != null) {
+            for (final String kitName : kitMap.keySet()) {
                 if (kitName.equalsIgnoreCase(name)) {
                     return kitName;
                 }
@@ -90,25 +112,32 @@ public class Kits implements IConf {
         return null;
     }
 
-    public void addKit(final String name, final List<String> lines, final long delay) {
+    public void addKit(String name, final List<String> lines, final long delay) {
+        name = name.replace('.', '_').replace('/', '_').toLowerCase(Locale.ENGLISH);
         // Will overwrite but w/e
-        config.setProperty("kits." + name + ".delay", delay);
-        config.setProperty("kits." + name + ".items", lines);
-        kits = _getKits();
-        config.save();
+        rootConfig.setProperty("kits." + name + ".delay", delay);
+        rootConfig.setProperty("kits." + name + ".items", lines);
+        parseKits();
+        rootConfig.save();
     }
 
-    public void removeKit(final String name) {
+    public void removeKit(String name) {
+        name = name.replace('.', '_').replace('/', '_').toLowerCase(Locale.ENGLISH);
+        if (!kitToConfigMap.containsKey(name) || !kitMap.containsKey(name)) {
+            return;
+        }
+
+        final EssentialsConfiguration config = kitToConfigMap.get(name);
         config.removeProperty("kits." + name);
-        kits = _getKits();
-        config.save();
+
+        config.blockingSave();
+        parseKits();
     }
 
     public String listKits(final net.ess3.api.IEssentials ess, final User user) throws Exception {
         try {
-            final CommentedConfigurationNode kits = config.getSection("kits");
             final StringBuilder list = new StringBuilder();
-            for (final String kitItem : ConfigurateUtil.getKeys(kits)) {
+            for (final String kitItem : kitMap.keySet()) {
                 if (user == null) {
                     list.append(" ").append(capitalCase(kitItem));
                 } else if (user.isAuthorized("essentials.kits." + kitItem.toLowerCase(Locale.ENGLISH))) {
diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commanddelkit.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commanddelkit.java
index 777fd29b2..6bb08d9df 100644
--- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commanddelkit.java
+++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commanddelkit.java
@@ -2,7 +2,6 @@ package com.earth2me.essentials.commands;
 
 import com.earth2me.essentials.CommandSource;
 import com.earth2me.essentials.Kit;
-import com.earth2me.essentials.config.ConfigurateUtil;
 import com.google.common.collect.Lists;
 import org.bukkit.Server;
 
@@ -38,7 +37,7 @@ public class Commanddelkit extends EssentialsCommand {
     @Override
     protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
         if (args.length == 1) {
-            return Lists.newArrayList(ConfigurateUtil.getKeys(ess.getKits().getKits()));
+            return Lists.newArrayList(ess.getKits().getKitKeys());
         }
         return Collections.emptyList();
     }
diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkit.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkit.java
index 10f2eacb0..28fc58911 100644
--- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkit.java
+++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkit.java
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
 import com.earth2me.essentials.CommandSource;
 import com.earth2me.essentials.Kit;
 import com.earth2me.essentials.User;
-import com.earth2me.essentials.config.ConfigurateUtil;
 import com.earth2me.essentials.utils.StringUtil;
 import org.bukkit.Server;
 
@@ -101,7 +100,7 @@ public class Commandkit extends EssentialsCommand {
         if (args.length == 1) {
             final List<String> options = new ArrayList<>();
             // TODO: Move all of this to its own method
-            for (final String kitName : ConfigurateUtil.getKeys(ess.getKits().getKits())) {
+            for (final String kitName : ess.getKits().getKitKeys()) {
                 if (!user.isAuthorized("essentials.kits." + kitName)) { // Only check perm, not time or money
                     continue;
                 }
@@ -118,7 +117,7 @@ public class Commandkit extends EssentialsCommand {
     @Override
     protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
         if (args.length == 1) {
-            return new ArrayList<>(ConfigurateUtil.getKeys(ess.getKits().getKits())); // TODO: Move this to its own method
+            return new ArrayList<>(ess.getKits().getKitKeys()); // TODO: Move this to its own method
         } else if (args.length == 2) {
             return getPlayers(server, sender);
         } else {
diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkitreset.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkitreset.java
index 82dc54921..09b1c7f79 100644
--- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkitreset.java
+++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandkitreset.java
@@ -2,7 +2,6 @@ package com.earth2me.essentials.commands;
 
 import com.earth2me.essentials.CommandSource;
 import com.earth2me.essentials.User;
-import com.earth2me.essentials.config.ConfigurateUtil;
 import org.bukkit.Server;
 
 import java.util.ArrayList;
@@ -59,7 +58,7 @@ public class Commandkitreset extends EssentialsCommand {
     @Override
     protected List<String> getTabCompleteOptions(Server server, CommandSource sender, String commandLabel, String[] args) {
         if (args.length == 1) {
-            return new ArrayList<>(ConfigurateUtil.getKeys(ess.getKits().getKits()));
+            return new ArrayList<>(ess.getKits().getKitKeys());
         } else if (args.length == 2 && sender.isAuthorized("essentials.kitreset.others", ess)) {
             return getPlayers(server, sender);
         } else {
diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandshowkit.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandshowkit.java
index 1da50851a..1b0fabd7a 100644
--- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandshowkit.java
+++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandshowkit.java
@@ -2,7 +2,6 @@ package com.earth2me.essentials.commands;
 
 import com.earth2me.essentials.Kit;
 import com.earth2me.essentials.User;
-import com.earth2me.essentials.config.ConfigurateUtil;
 import org.bukkit.Server;
 
 import java.util.ArrayList;
@@ -34,7 +33,7 @@ public class Commandshowkit extends EssentialsCommand {
     @Override
     protected List<String> getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) {
         if (args.length == 1) {
-            return new ArrayList<>(ConfigurateUtil.getKeys(ess.getKits().getKits())); // TODO: Move this to its own method
+            return new ArrayList<>(ess.getKits().getKitKeys()); // TODO: Move this to its own method
         } else {
             return Collections.emptyList();
         }
diff --git a/Essentials/src/main/resources/kits.yml b/Essentials/src/main/resources/kits.yml
index c725664fa..cefc3ed8b 100644
--- a/Essentials/src/main/resources/kits.yml
+++ b/Essentials/src/main/resources/kits.yml
@@ -9,6 +9,10 @@
 # {PLAYER} will show the player's displayname instead of username.
 # 'delay' refers to the cooldown between how often you can use each kit, measured in seconds.
 # Set delay to -1 for a one time kit.
+#
+# In addition, you can also organize your kits into separate files under the `kits` subdirectory.
+# Essentials will treat all .yml files in the `kits` subdirectory as kits files, and will add any kits from those files along with the kits in `kits.yml`.
+# Any file in the `kits` subdirectory must be formatted in the same way as this file. This allows you to define multiple kits in each file.
 # For more information, visit http://wiki.ess3.net/wiki/Kits
 kits:
   tools: