diff --git a/Nautilus/Assets/ModPrefabCache.cs b/Nautilus/Assets/ModPrefabCache.cs
index 73b52670a..e3cecb083 100644
--- a/Nautilus/Assets/ModPrefabCache.cs
+++ b/Nautilus/Assets/ModPrefabCache.cs
@@ -110,6 +110,7 @@ public void EnterPrefabIntoCache(GameObject prefab)
             else
             {
                 prefab.transform.parent = _prefabRoot;
+                ResetIds(prefab);
                 prefab.SetActive(true);
             }
         }
@@ -121,7 +122,7 @@ public void EnterPrefabIntoCache(GameObject prefab)
 
     public void RemoveCachedPrefab(string classId)
     {
-        if(Entries.TryGetValue(classId, out var prefab))
+        if (Entries.TryGetValue(classId, out var prefab))
         {
             if(!prefab.IsPrefab())
                 Destroy(prefab);
@@ -129,4 +130,20 @@ public void RemoveCachedPrefab(string classId)
             Entries.Remove(classId);
         }
     }
+
+    private void ResetIds(GameObject prefab)
+    {
+        var uniqueIds = prefab.GetAllComponentsInChildren<UniqueIdentifier>();
+
+        foreach (var uniqueId in uniqueIds)
+        {
+            if (string.IsNullOrEmpty(uniqueId.id))
+            {
+                continue;
+            }
+            
+            UniqueIdentifier.identifiers.Remove(uniqueId.id);
+            uniqueId.id = null;
+        }
+    }
 }
\ No newline at end of file
diff --git a/Nautilus/Handlers/CoordinatedSpawnsHandler.cs b/Nautilus/Handlers/CoordinatedSpawnsHandler.cs
index 1efc1fe29..44141bdd0 100644
--- a/Nautilus/Handlers/CoordinatedSpawnsHandler.cs
+++ b/Nautilus/Handlers/CoordinatedSpawnsHandler.cs
@@ -3,6 +3,7 @@
 using System.Linq;
 using Nautilus.Assets;
 using Nautilus.Patchers;
+using Nautilus.Utility;
 using Newtonsoft.Json;
 using UnityEngine;
 
@@ -19,11 +20,17 @@ public static class CoordinatedSpawnsHandler
     /// <param name="spawnInfo">the SpawnInfo to spawn.</param>
     public static void RegisterCoordinatedSpawn(SpawnInfo spawnInfo)
     {
-        if (!LargeWorldStreamerPatcher.spawnInfos.Add(spawnInfo))
+        if (!LargeWorldStreamerPatcher.SpawnInfos.Add(spawnInfo))
+        {
+            InternalLogger.Error($"SpawnInfo {spawnInfo} already registered.");
             return;
-        
-        if (uGUI.isMainLevel)
-            LargeWorldStreamerPatcher.CreateSpawner(spawnInfo);
+        }
+
+        if (LargeWorldStreamer.main)
+        {
+            var batch = LargeWorldStreamer.main.GetContainingBatch(spawnInfo.SpawnPosition);
+            LargeWorldStreamerPatcher.BatchToSpawnInfos.GetOrAddNew(batch).Add(spawnInfo);
+        }
     }
 
     /// <summary>
diff --git a/Nautilus/MonoBehaviours/EntitySpawner.cs b/Nautilus/MonoBehaviours/EntitySpawner.cs
index 67040419a..f4826d741 100644
--- a/Nautilus/MonoBehaviours/EntitySpawner.cs
+++ b/Nautilus/MonoBehaviours/EntitySpawner.cs
@@ -1,74 +1,81 @@
+namespace Nautilus.MonoBehaviours;
+
 using System.Collections;
-using Nautilus.Extensions;
+using System.Collections.Generic;
 using Nautilus.Handlers;
 using Nautilus.Patchers;
 using Nautilus.Utility;
 using UnityEngine;
 using UWE;
 
-namespace Nautilus.MonoBehaviours;
-
 internal class EntitySpawner : MonoBehaviour
 {
-    internal SpawnInfo spawnInfo;
+    internal Int3 batchId;
+    internal IReadOnlyCollection<SpawnInfo> spawnInfos;
+    internal bool global;
 
-    void Start()
+    private IEnumerator Start()
     {
-        StartCoroutine(SpawnAsync());
+        yield return SpawnAsync();
+        Destroy(gameObject);
     }
 
-    IEnumerator SpawnAsync()
+    private IEnumerator SpawnAsync()
     {
-        string stringToLog = spawnInfo.Type switch
-        {
-            SpawnInfo.SpawnType.ClassId => spawnInfo.ClassId,
-            _ => spawnInfo.TechType.AsString()
-        };
-
-        TaskResult<GameObject> task = new();
-        yield return GetPrefabAsync(task);
-
-        GameObject prefab = task.Get();
-        if (prefab == null)
-        {
-            InternalLogger.Error($"no prefab found for {stringToLog}; process for Coordinated Spawn canceled.");
-            Destroy(gameObject);
-            yield break;
-        }
-        
-        if (!prefab.IsPrefab())
-        {
-            prefab.SetActive(false);
-        }
-
-        GameObject obj = UWE.Utils.InstantiateDeactivated(prefab, spawnInfo.SpawnPosition, spawnInfo.Rotation, spawnInfo.ActualScale);
-
-        LargeWorldEntity lwe = obj.GetComponent<LargeWorldEntity>();
-
         LargeWorldStreamer lws = LargeWorldStreamer.main;
         yield return new WaitUntil(() => lws != null && lws.IsReady()); // first we make sure the world streamer is initialized
 
-        // non-global objects cannot be spawned in unloaded terrain so we need to wait
-        if (lwe is {cellLevel: not (LargeWorldEntity.CellLevel.Batch or LargeWorldEntity.CellLevel.Global)})
+        if (!global)
         {
-            Int3 batch = lws.GetContainingBatch(spawnInfo.SpawnPosition);
-            yield return new WaitUntil(() => lws.IsBatchReadyToCompile(batch)); // then we wait until the terrain is fully loaded (must be checked on each frame for faster spawns)
+            // then we wait until the terrain is fully loaded (must be checked on each frame for faster spawns)
+            yield return new WaitUntil(() => lws.IsBatchReadyToCompile(batchId));
         }
 
         LargeWorld lw = LargeWorld.main;
-
+        
         yield return new WaitUntil(() => lw != null && lw.streamer.globalRoot != null); // need to make sure global root is ready too for global spawns.
+
+        foreach (var spawnInfo in spawnInfos)
+        {
+            string stringToLog = spawnInfo.Type switch
+            {
+                SpawnInfo.SpawnType.ClassId => spawnInfo.ClassId,
+                _ => spawnInfo.TechType.AsString()
+            };
+            
+            InternalLogger.Debug($"Spawning {stringToLog}");
             
-        lw.streamer.cellManager.RegisterEntity(obj);
+            TaskResult<GameObject> task = new();
+            yield return GetPrefabAsync(spawnInfo, task);
 
-        obj.SetActive(true);
+            GameObject prefab = task.Get();
+            if (prefab == null)
+            {
+                InternalLogger.Error($"no prefab found for {stringToLog}; process for Coordinated Spawn canceled.");
+                continue;
+            }
 
-        LargeWorldStreamerPatcher.savedSpawnInfos.Add(spawnInfo);
+            LargeWorldEntity lwe = prefab.GetComponent<LargeWorldEntity>();
 
-        Destroy(gameObject);
+            if (!lwe)
+            {
+                InternalLogger.Error($"No LargeWorldEntity component found for prefab '{stringToLog}'; process for Coordinated Spawn canceled.");
+                continue;
+            }
+
+            GameObject obj = Instantiate(prefab, spawnInfo.SpawnPosition, spawnInfo.Rotation);
+            obj.transform.localScale = spawnInfo.ActualScale;
+
+            obj.SetActive(true);
+
+            LargeWorldEntity.Register(obj);
+
+            LargeWorldStreamerPatcher.SavedSpawnInfos.Add(spawnInfo);
+            InternalLogger.Debug($"spawned {stringToLog}.");
+        }
     }
 
-    IEnumerator GetPrefabAsync(IOut<GameObject> gameObject)
+    private IEnumerator GetPrefabAsync(SpawnInfo spawnInfo, IOut<GameObject> gameObject)
     {
         GameObject obj;
 
diff --git a/Nautilus/Patchers/LargeWorldStreamerPatcher.cs b/Nautilus/Patchers/LargeWorldStreamerPatcher.cs
index 6d333c7c6..ed6024d5c 100644
--- a/Nautilus/Patchers/LargeWorldStreamerPatcher.cs
+++ b/Nautilus/Patchers/LargeWorldStreamerPatcher.cs
@@ -1,32 +1,44 @@
+using System.Collections;
+
+namespace Nautilus.Patchers;
+
 using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using HarmonyLib;
+using Nautilus.Assets;
 using Nautilus.Handlers;
 using Nautilus.Json.Converters;
 using Nautilus.MonoBehaviours;
 using Nautilus.Utility;
 using Newtonsoft.Json;
 using UnityEngine;
+using UnityEngine.AddressableAssets;
+using UnityEngine.ResourceManagement.AsyncOperations;
+using UWE;
 
-namespace Nautilus.Patchers;
-
-internal class LargeWorldStreamerPatcher
+internal static class LargeWorldStreamerPatcher
 {
     internal static void Patch(Harmony harmony)
     {
-        System.Reflection.MethodInfo initializeOrig = AccessTools.Method(typeof(LargeWorldStreamer), nameof(LargeWorldStreamer.Initialize));
+        MethodInfo initializeOrig = AccessTools.Method(typeof(LargeWorldStreamer), nameof(LargeWorldStreamer.Initialize));
         HarmonyMethod initPostfix = new(AccessTools.Method(typeof(LargeWorldStreamerPatcher), nameof(InitializePostfix)));
         harmony.Patch(initializeOrig, postfix: initPostfix);
+
+        MethodInfo onBatchFullyLoadedOrig = AccessTools.Method(typeof(LargeWorldStreamer), nameof(LargeWorldStreamer.OnBatchFullyLoaded));
+        HarmonyMethod onBatchFullyLoadedPostfix = new(AccessTools.Method(typeof(LargeWorldStreamerPatcher), nameof(OnBatchFullyLoadedPostfix)));
+        harmony.Patch(onBatchFullyLoadedOrig, postfix: onBatchFullyLoadedPostfix);
     }
+    
+    internal static readonly HashSet<SpawnInfo> SpawnInfos = new();
+    internal static readonly HashSet<SpawnInfo> SavedSpawnInfos = new();
+    internal static readonly Dictionary<Int3, HashSet<SpawnInfo>> BatchToSpawnInfos = new();
 
-    internal static readonly HashSet<SpawnInfo> spawnInfos = new();
-    internal static readonly HashSet<SpawnInfo> savedSpawnInfos = new();
-        
-    private static readonly HashSet<SpawnInfo> initialSpawnInfos = new();
+    private static readonly HashSet<SpawnInfo> _initialSpawnInfos = new();
 
-    private static bool initialized;
+    private static bool _initialized;
 
     private static void InitializePostfix()
     {
@@ -43,23 +55,135 @@ private static void InitializePostfix()
                 List<SpawnInfo> deserializedList = JsonConvert.DeserializeObject<List<SpawnInfo>>(reader.ReadToEnd(), new Vector3Converter(), new QuaternionConverter());
                 if (deserializedList is not null)
                 {
-                    savedSpawnInfos.AddRange(deserializedList);
+                    SavedSpawnInfos.AddRange(deserializedList);
                 }
 
                 reader.Close();
             }
             catch (Exception ex)
             {
-                InternalLogger.Error($"Failed to load Saved spawn data from {file}\nSkipping static spawning until fixed!\n{ex}");
+                InternalLogger.Error($"Failed to load Saved spawn data from {file}\nSkipping Coordinated spawning until fixed!\n{ex}");
                 reader.Close();
                 return;
             }
         }
 
-        spawnInfos.RemoveWhere(s => savedSpawnInfos.Contains(s));
-
-        InitializeSpawners();
+        SpawnInfos.RemoveWhere(s => SavedSpawnInfos.Contains(s));
         InternalLogger.Debug("Coordinated Spawns have been initialized in the current save.");
+
+        var globalSpawns = new HashSet<SpawnInfo>();
+
+        // Preload all the prefabs for faster spawning.
+        new List<SpawnInfo>(SpawnInfos).Do((info) =>
+        {
+            string keyToCheck = info.Type switch
+            {
+                SpawnInfo.SpawnType.TechType => CraftData.GetClassIdForTechType(info.TechType),
+                _ => info.ClassId
+            };
+            if (!PrefabDatabase.TryGetPrefabFilename(keyToCheck, out string prefabName))
+            {
+                InternalLogger.Error($"Failed to get prefab name for {keyToCheck}; process for Coordinated Spawn canceled.");
+                SpawnInfos.Remove(info);
+                return;
+            }
+
+            if (PrefabHandler.Prefabs.TryGetInfoForFileName(prefabName, out var prefabInfo))
+            {
+                InternalLogger.Debug($"Preloading {keyToCheck}");
+                CoroutineHost.StartCoroutine(PreloadModdedPrefab(info, prefabInfo));
+            }
+            else
+            {
+                var task = new AssetReferenceGameObject(prefabName).LoadAssetAsync();
+                task.Completed += (t) =>
+                {
+                    if (t.Status != AsyncOperationStatus.Succeeded)
+                    {
+                        InternalLogger.Error($"Failed to preload {keyToCheck} with error: {t.OperationException}");
+                        return;
+                    }
+
+                    var prefab = t.Result;
+                    if (prefab == null)
+                    {
+                        InternalLogger.Error($"no prefab found for {keyToCheck}; process for Coordinated Spawn canceled.");
+                        SpawnInfos.Remove(info);
+                        return;
+                    }
+
+                    LargeWorldEntity lwe = prefab.GetComponent<LargeWorldEntity>();
+                    if (lwe is null)
+                    {
+                        InternalLogger.Error($"No LargeWorldEntity found on {keyToCheck}; Please ensure the prefab has a LargeWorldEntity component when using Coordinated Spawns.");
+                        lwe = prefab.AddComponent<LargeWorldEntity>();
+                    }
+
+                    if (lwe is { cellLevel: LargeWorldEntity.CellLevel.Global })
+                    {
+                        globalSpawns.Add(info);
+                        InternalLogger.Debug($"Init: Created spawner for {keyToCheck} at the Global level.");
+                        SpawnInfos.Remove(info);
+                    }
+
+                    InternalLogger.Debug($"Preloaded {keyToCheck}");
+                };
+            }
+        });
+
+        CreateSpawner(LargeWorldStreamer.main.GetContainingBatch(Vector3.zero), globalSpawns, true);
+
+        foreach (var spawnInfo in SpawnInfos)
+        {
+            var batch = LargeWorldStreamer.main.GetContainingBatch(spawnInfo.SpawnPosition);
+
+            if (globalSpawns.Contains(spawnInfo))
+            {
+                continue;
+            }
+            
+            BatchToSpawnInfos.GetOrAddNew(batch).Add(spawnInfo);
+        }
+    }
+    
+    private static void OnBatchFullyLoadedPostfix(Int3 batchId)
+    {
+        if (BatchToSpawnInfos.TryGetValue(batchId, out var spawnInfos))
+        {
+            CreateSpawner(batchId, spawnInfos, false);
+            SpawnInfos.RemoveRange(spawnInfos);
+            BatchToSpawnInfos.Remove(batchId);
+        }
+    }
+
+    private static IEnumerator PreloadModdedPrefab(SpawnInfo info, PrefabInfo prefabInfo)
+    {
+        var request = new ModPrefabRequest(prefabInfo);
+        yield return request;
+
+        if (!request.TryGetPrefab(out var prefab))
+        {
+            InternalLogger.Error($"no prefab found for {prefabInfo.ClassID}; process for Coordinated Spawn canceled.");
+            SpawnInfos.Remove(info);
+            yield break;
+        }
+        LargeWorldEntity lwe = prefab.GetComponent<LargeWorldEntity>();
+        if (lwe is null)
+        {
+            InternalLogger.Error($"No LargeWorldEntity found on {prefabInfo.ClassID}; Please ensure the prefab has a LargeWorldEntity component when using Coordinated Spawns.");
+            lwe = prefab.AddComponent<LargeWorldEntity>();
+        }
+        if (lwe is { cellLevel: LargeWorldEntity.CellLevel.Global })
+        {
+            var batch = LargeWorldStreamer.main.GetContainingBatch(info.SpawnPosition);
+            CreateSpawner(batch, new []{info}, true);
+            InternalLogger.Debug($"Preload: Created spawner for {info.ClassId} at the Global level.");
+            SpawnInfos.Remove(info);
+            if (BatchToSpawnInfos.TryGetValue(batch, out var spawnInfos))
+            {
+                spawnInfos.Remove(info);
+            }
+        }
     }
 
     private static void SaveData()
@@ -68,7 +192,7 @@ private static void SaveData()
         using StreamWriter writer = new(file);
         try
         {
-            string data = JsonConvert.SerializeObject(savedSpawnInfos, Formatting.Indented, new Vector3Converter(), new QuaternionConverter());
+            string data = JsonConvert.SerializeObject(SavedSpawnInfos, Formatting.Indented, new Vector3Converter(), new QuaternionConverter());
             writer.Write(data);
             writer.Flush();
             writer.Close();
@@ -79,43 +203,35 @@ private static void SaveData()
             writer.Close();
         }
     }
-        
+
     // We keep an initial copy of the spawn infos so Coordinated Spawns also works if you quit to main menu.
     private static void InitializeSpawnInfos()
     {
-        if (initialized)
+        if (_initialized)
         {
             // we already have an initialSpawnInfos initialized, refresh our spawnInfos List.
-            savedSpawnInfos.Clear();
-            foreach (SpawnInfo spawnInfo in initialSpawnInfos.Where(spawnInfo => !spawnInfos.Contains(spawnInfo)))
+            SavedSpawnInfos.Clear();
+            foreach (SpawnInfo spawnInfo in _initialSpawnInfos.Where(spawnInfo => !SpawnInfos.Contains(spawnInfo)))
             {
-                spawnInfos.Add(spawnInfo);
+                SpawnInfos.Add(spawnInfo);
             }
             return;
         }
-            
-        initialSpawnInfos.AddRange(spawnInfos);
-        SaveUtils.RegisterOnSaveEvent(SaveData);
-        initialized = true;
-    }
 
-    private static void InitializeSpawners()
-    {
-        foreach (SpawnInfo spawnInfo in spawnInfos)
-        {
-            CreateSpawner(spawnInfo);
-        }
+        _initialSpawnInfos.AddRange(SpawnInfos);
+        SaveUtils.RegisterOnSaveEvent(SaveData);
+        _initialized = true;
     }
 
-    internal static void CreateSpawner(SpawnInfo spawnInfo)
+    private static void CreateSpawner(Int3 batch, IReadOnlyCollection<SpawnInfo> spawnInfos, bool global)
     {
-        string keyToCheck = spawnInfo.Type switch
-        {
-            SpawnInfo.SpawnType.TechType => spawnInfo.TechType.AsString(),
-            _ => spawnInfo.ClassId
-        };
-
-        GameObject obj = new($"{keyToCheck}Spawner");
-        obj.EnsureComponent<EntitySpawner>().spawnInfo = spawnInfo;
+        var centerPosition = LargeWorldStreamer.main.GetBatchCenter(batch);
+        InternalLogger.Debug($"Creating Spawner for batch: {batch} at {centerPosition}");
+        GameObject obj = new($"{batch} Spawner");
+        obj.transform.position = centerPosition;
+        var spawner = obj.EnsureComponent<EntitySpawner>();
+        spawner.batchId = batch;
+        spawner.spawnInfos = spawnInfos;
+        spawner.global = global;
     }
 }
\ No newline at end of file
diff --git a/Nautilus/Patchers/VehicleUpgradesPatcher.cs b/Nautilus/Patchers/VehicleUpgradesPatcher.cs
index 27ff03afe..4bdb577bd 100644
--- a/Nautilus/Patchers/VehicleUpgradesPatcher.cs
+++ b/Nautilus/Patchers/VehicleUpgradesPatcher.cs
@@ -24,7 +24,6 @@ internal class VehicleUpgradesPatcher
     internal static void Patch(Harmony harmony)
     {
         InternalLogger.Debug("VehicleUpgradePatcher: attempting patch...");
-        HarmonyFileLog.Enabled = true;
         try
         {
             harmony.PatchAll(typeof(VehicleUpgradesPatcher));