diff --git a/src/main/java/net/minestom/server/utils/PacketUtils.java b/src/main/java/net/minestom/server/utils/PacketUtils.java
index 96e9d0366..ec1726134 100644
--- a/src/main/java/net/minestom/server/utils/PacketUtils.java
+++ b/src/main/java/net/minestom/server/utils/PacketUtils.java
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
@@ -261,12 +262,12 @@ public final class PacketUtils {
     }
 
     private static final class ViewableStorage {
-        private final Viewable viewable;
+        private final WeakReference<Viewable> viewable;
         private final Map<PlayerConnection, List<IntIntPair>> entityIdMap = new HashMap<>();
         private final BinaryBuffer buffer = PooledBuffers.get();
 
         private ViewableStorage(Viewable viewable) {
-            this.viewable = viewable;
+            this.viewable = new WeakReference<>(viewable);
             PooledBuffers.registerBuffer(this, buffer);
         }
 
@@ -274,7 +275,7 @@ public final class PacketUtils {
             final ByteBuffer framedPacket = createFramedPacket(serverPacket).flip();
             final int packetSize = framedPacket.limit();
             if (packetSize >= buffer.capacity()) {
-                processSingle(framedPacket, connection);
+                process(new SingleEntry(framedPacket, connection));
                 return;
             }
             if (!buffer.canWrite(packetSize)) process();
@@ -287,9 +288,11 @@ public final class PacketUtils {
             }
         }
 
-        private synchronized void process() {
+        private synchronized void process(@Nullable SingleEntry singleEntry) {
             if (buffer.writerOffset() == 0)
                 return; // TODO: there is nothing in the buffer, remove from VIEWABLE_STORAGE_MAP
+            final Viewable viewable = this.viewable.get();
+            if (viewable == null) return;
             for (Player player : viewable.getViewers()) {
                 PlayerConnection connection = player.getPlayerConnection();
                 Consumer<ByteBuffer> writer = connection instanceof PlayerSocketConnection
@@ -316,21 +319,28 @@ public final class PacketUtils {
                     ByteBuffer remainSlice = buffer.asByteBuffer(lastWrite, remaining);
                     writer.accept(remainSlice);
                 }
+
+                // Handle single entry
+                if (singleEntry != null && !singleEntry.exception.equals(connection)) {
+                    writer.accept(singleEntry.buffer.position(0));
+                }
             }
             // Clear state
             this.entityIdMap.clear();
             this.buffer.clear();
         }
 
-        private synchronized void processSingle(ByteBuffer buffer, PlayerConnection exception) {
-            process();
-            for (Player player : viewable.getViewers()) {
-                PlayerConnection connection = player.getPlayerConnection();
-                if (Objects.equals(connection, exception)) continue;
-                if (connection instanceof PlayerSocketConnection) {
-                    ((PlayerSocketConnection) connection).write(buffer.position(0));
-                }
-                // TODO for non-socket connection
+        private void process() {
+            process(null);
+        }
+
+        private static final class SingleEntry {
+            private final ByteBuffer buffer;
+            private final PlayerConnection exception;
+
+            public SingleEntry(ByteBuffer buffer, PlayerConnection exception) {
+                this.buffer = buffer;
+                this.exception = exception;
             }
         }
     }