diff --git a/src/main/java/net/knarcraft/stargate/Stargate.java b/src/main/java/net/knarcraft/stargate/Stargate.java
index 1fea40c..dfb3ea7 100644
--- a/src/main/java/net/knarcraft/stargate/Stargate.java
+++ b/src/main/java/net/knarcraft/stargate/Stargate.java
@@ -3,6 +3,7 @@ package net.knarcraft.stargate;
 import net.knarcraft.stargate.command.CommandStarGate;
 import net.knarcraft.stargate.command.StarGateTabCompleter;
 import net.knarcraft.stargate.container.BlockChangeRequest;
+import net.knarcraft.stargate.container.ChunkUnloadRequest;
 import net.knarcraft.stargate.listener.BlockEventListener;
 import net.knarcraft.stargate.listener.BungeeCordListener;
 import net.knarcraft.stargate.listener.EntityEventListener;
@@ -15,6 +16,7 @@ import net.knarcraft.stargate.portal.GateHandler;
 import net.knarcraft.stargate.portal.Portal;
 import net.knarcraft.stargate.portal.PortalHandler;
 import net.knarcraft.stargate.thread.BlockChangeThread;
+import net.knarcraft.stargate.thread.ChunkUnloadThread;
 import net.knarcraft.stargate.thread.StarGateThread;
 import net.knarcraft.stargate.utility.EconomyHandler;
 import net.knarcraft.stargate.utility.FileHelper;
@@ -31,6 +33,7 @@ import org.bukkit.plugin.PluginManager;
 import org.bukkit.plugin.java.JavaPlugin;
 import org.bukkit.plugin.java.JavaPluginLoader;
 import org.bukkit.plugin.messaging.Messenger;
+import org.bukkit.scheduler.BukkitScheduler;
 
 import java.io.File;
 import java.io.IOException;
@@ -38,6 +41,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.PriorityQueue;
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.logging.Level;
@@ -50,6 +54,7 @@ public class Stargate extends JavaPlugin {
     public static final Queue<BlockChangeRequest> blockChangeRequestQueue = new LinkedList<>();
     public static final ConcurrentLinkedQueue<Portal> openPortalsQueue = new ConcurrentLinkedQueue<>();
     public static final ConcurrentLinkedQueue<Portal> activePortalsQueue = new ConcurrentLinkedQueue<>();
+    public static final Queue<ChunkUnloadRequest> chunkUnloadQueue = new PriorityQueue<>();
 
     //Amount of seconds before deactivating/closing portals
     private static final int activeTime = 10;
@@ -334,8 +339,10 @@ public class Stargate extends JavaPlugin {
         setupVaultEconomy();
 
         //Run necessary threads
-        getServer().getScheduler().runTaskTimer(this, new StarGateThread(), 0L, 100L);
-        getServer().getScheduler().runTaskTimer(this, new BlockChangeThread(), 0L, 1L);
+        BukkitScheduler scheduler = getServer().getScheduler();
+        scheduler.runTaskTimer(this, new StarGateThread(), 0L, 100L);
+        scheduler.runTaskTimer(this, new BlockChangeThread(), 0L, 1L);
+        scheduler.runTaskTimer(this, new ChunkUnloadThread(), 0L, 100L);
 
         this.registerCommands();
     }
@@ -615,4 +622,23 @@ public class Stargate extends JavaPlugin {
         }
     }
 
+    /**
+     * Gets the chunk unload queue containing chunks to unload
+     *
+     * @return <p>The chunk unload queue</p>
+     */
+    public static Queue<ChunkUnloadRequest> getChunkUnloadQueue() {
+        return chunkUnloadQueue;
+    }
+
+    /**
+     * Adds a new chunk unload request to the chunk unload queue
+     *
+     * @param request <p>The new chunk unload request to add</p>
+     */
+    public static void addChunkUnloadRequest(ChunkUnloadRequest request) {
+        chunkUnloadQueue.removeIf((item) -> item.getChunkToUnload().equals(request.getChunkToUnload()));
+        chunkUnloadQueue.add(request);
+    }
+
 }
diff --git a/src/main/java/net/knarcraft/stargate/container/ChunkUnloadRequest.java b/src/main/java/net/knarcraft/stargate/container/ChunkUnloadRequest.java
new file mode 100644
index 0000000..a2657ca
--- /dev/null
+++ b/src/main/java/net/knarcraft/stargate/container/ChunkUnloadRequest.java
@@ -0,0 +1,54 @@
+package net.knarcraft.stargate.container;
+
+import org.bukkit.Chunk;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Requests the unloading of a chunk which has been previously loaded by the Stargate plugin
+ */
+public class ChunkUnloadRequest implements Comparable<ChunkUnloadRequest> {
+
+    private final Long unloadNanoTime;
+    private final Chunk chunkToUnload;
+
+    /**
+     * Instantiates a new chunk unloading request
+     *
+     * @param chunkToUnload   <p>The chunk to request the unloading of</p>
+     * @param timeUntilUnload <p>The time in milliseconds to wait before unloading the chunk</p>
+     */
+    public ChunkUnloadRequest(Chunk chunkToUnload, Long timeUntilUnload) {
+        this.chunkToUnload = chunkToUnload;
+        long systemNanoTime = System.nanoTime();
+        this.unloadNanoTime = systemNanoTime + (timeUntilUnload * 1000000);
+    }
+
+    /**
+     * Gets the chunk to unload
+     *
+     * @return <p>The chunk to unload</p>
+     */
+    public Chunk getChunkToUnload() {
+        return this.chunkToUnload;
+    }
+
+    /**
+     * Gets the time system nano time denoting at which time the unload request should be executed
+     *
+     * @return <p>The system nano time denoting when the chunk is to be unloaded</p>
+     */
+    public Long getUnloadNanoTime() {
+        return this.unloadNanoTime;
+    }
+
+    @Override
+    public String toString() {
+        return "{" + chunkToUnload + ", " + unloadNanoTime + "}";
+    }
+
+    @Override
+    public int compareTo(@NotNull ChunkUnloadRequest otherRequest) {
+        return unloadNanoTime.compareTo(otherRequest.unloadNanoTime);
+    }
+
+}
diff --git a/src/main/java/net/knarcraft/stargate/portal/Portal.java b/src/main/java/net/knarcraft/stargate/portal/Portal.java
index e656c9e..2f476c8 100644
--- a/src/main/java/net/knarcraft/stargate/portal/Portal.java
+++ b/src/main/java/net/knarcraft/stargate/portal/Portal.java
@@ -3,6 +3,7 @@ package net.knarcraft.stargate.portal;
 import net.knarcraft.stargate.Stargate;
 import net.knarcraft.stargate.container.BlockChangeRequest;
 import net.knarcraft.stargate.container.BlockLocation;
+import net.knarcraft.stargate.container.ChunkUnloadRequest;
 import net.knarcraft.stargate.container.RelativeBlockVector;
 import net.knarcraft.stargate.event.StargateActivateEvent;
 import net.knarcraft.stargate.event.StargateCloseEvent;
@@ -501,8 +502,6 @@ public class Portal {
 
         //Load chunks to make sure not to teleport to the void
         loadChunks();
-        Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate,
-                this::unloadChunks, 4000);
 
         //If no event is passed in, assume it's a teleport, and act as such
         if (event == null) {
@@ -551,8 +550,6 @@ public class Portal {
 
         //Load chunks to make sure not to teleport to the void
         loadChunks();
-        Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate,
-                this::unloadChunks, 4000);
 
         if (!passengers.isEmpty()) {
             if (vehicle instanceof RideableMinecart || vehicle instanceof Boat) {
@@ -628,7 +625,7 @@ public class Portal {
      * but there needs to be a delay between teleporting the vehicle and teleporting and adding the passenger.</p>
      *
      * @param targetVehicle <p>The vehicle to add the passenger to</p>
-     * @param passenger <p>The passenger to teleport and add</p>
+     * @param passenger     <p>The passenger to teleport and add</p>
      */
     private void teleportAndAddPassenger(Vehicle targetVehicle, Entity passenger) {
         if (!passenger.teleport(targetVehicle.getLocation())) {
@@ -770,21 +767,15 @@ public class Portal {
         return traveller;
     }
 
-    /**
-     * Unloads the chunks outside the portal's entrance
-     */
-    private void unloadChunks() {
-        for (Chunk chunk : getChunksToLoad()) {
-            chunk.removePluginChunkTicket(Stargate.stargate);
-        }
-    }
-
     /**
      * Loads the chunks outside the portal's entrance
      */
     private void loadChunks() {
         for (Chunk chunk : getChunksToLoad()) {
             chunk.addPluginChunkTicket(Stargate.stargate);
+            //Allow the chunk to unload after 3 seconds
+            Stargate.addChunkUnloadRequest(new ChunkUnloadRequest(chunk, 3000L));
+            Stargate.debug("loadChunks", "Added chunk unloading request for chunk " + chunk);
         }
     }
 
diff --git a/src/main/java/net/knarcraft/stargate/thread/ChunkUnloadThread.java b/src/main/java/net/knarcraft/stargate/thread/ChunkUnloadThread.java
new file mode 100644
index 0000000..49f0757
--- /dev/null
+++ b/src/main/java/net/knarcraft/stargate/thread/ChunkUnloadThread.java
@@ -0,0 +1,36 @@
+package net.knarcraft.stargate.thread;
+
+import net.knarcraft.stargate.Stargate;
+import net.knarcraft.stargate.container.ChunkUnloadRequest;
+import org.bukkit.Chunk;
+
+import java.util.Queue;
+
+/**
+ * Unloads chunks which should no longer be forced to stay loaded
+ */
+public class ChunkUnloadThread implements Runnable {
+
+    @Override
+    public void run() {
+        long systemNanoTime = System.nanoTime();
+        Queue<ChunkUnloadRequest> unloadQueue = Stargate.getChunkUnloadQueue();
+
+        //Peek at the first element to check if the chunk should be unloaded
+        ChunkUnloadRequest firstElement = unloadQueue.peek();
+        if (firstElement != null) {
+            Stargate.debug("ChunkUnloadThread", "Found chunk unload request: " + firstElement);
+            Stargate.debug("ChunkUnloadThread", "Current time: " + systemNanoTime);
+        }
+        //Repeat until all un-loadable chunks have been processed
+        while (firstElement != null && firstElement.getUnloadNanoTime() < systemNanoTime) {
+            unloadQueue.remove();
+            Chunk chunkToUnload = firstElement.getChunkToUnload();
+            //Allow the chunk to be unloaded
+            chunkToUnload.removePluginChunkTicket(Stargate.stargate);
+            Stargate.debug("ChunkUnloadThread", "Unloaded chunk " + chunkToUnload);
+            firstElement = unloadQueue.peek();
+        }
+    }
+
+}