As a Roblox developer, it is currently too hard to reliably manage the loading and unloading of critical, non-visual game components when using StreamingEnabled.
Currently, StreamingEnabled applies to the entire Workspace, automatically determining what to stream based on the player’s camera position. This blanket behavior is problematic because many games have functional objects that must reside in the Workspace but contain core game logic that must be loaded and persistent on the client, regardless of the player’s proximity.
Examples of parts that are traditionally placed in the Workspace but should not be streamed out include:
Server-Side Logic Parts: Parts used for server-side hit detection, large game boundaries, or persistent event triggers that need to be in the Workspace for optimal spatial querying or physics interaction.
Client-Critical Assets: Small functional models, UI anchors, or persistent local scripts that are parented to a part in the Workspace and are necessary for continuous client-side operations (like custom pathfinding visualizations or localized effects).
“Invisible” Map Structures: Complex collision hulls or large, invisible block-out volumes that are vital for world integrity but are not meant to be streamed in/out alongside the visible environment.
The current workaround requires moving these critical parts out of the Workspace into containers like ServerStorage or ReplicatedStorage. However, this can complicate code logic, require developers to manually handle replication and parenting back to the Workspace on client load, and break assumptions made by built-in Roblox systems (like the physics engine or simple script references) that expect components to be in the Workspace hierarchy.
If Roblox is able to address this issue, it would improve my development experience because it would allow developers to use the powerful performance features of StreamingEnabled exclusively on the visual, geometric components of the game (e.g., the map, terrain, props), while guaranteeing that all critical game logic, functional models, and boundary parts within the Workspace remain loaded and reliable.
This would lead to:
More Robust Game Logic: Eliminating the risk of core game functionality being unloaded and causing client-side errors, missing triggers, or broken physics interactions.
Simplified Hierarchy: Developers could keep all their world-related components in the Workspace, as intended, without relying on complex workarounds to manage streaming behavior.
Better Optimization: The streaming system could be directed to focus its efforts only on the visual assets, potentially improving the efficiency of the streaming calculation itself.
The ideal implementation would be a property, perhaps an AllowedStreamingContainers list, that could be set on the Workspace or ContentProvider, which tells the engine that only the contents of the specified containers (e.g., a folder named “StreamableMapPieces”) should be considered for streaming, while all other objects in the Workspace are treated as non-streamable (always loaded).
I hate using this thread as a chat, but Persistent never gets streamed out. There’s no way to prevent streaming for a model that is a descendant of a replicated container (ex: Workspace).
This is such a good suggestion I am working on a game right now and this change would be nice for what I’m doing but I decided to make my own StreamingEnabled custom for the game
As others have pointed out on this thread, if what you are looking for is a way to prevent instances under workspace from ever streaming out, so they are always present on clients, then putting them inside a model and setting the model to be persistent is how we support this currently.
Would it be possible for you guys to make persistent models reliably replicate so they act exactly like they do under streaming disabled?
Streaming is only desirable for non-essential parts of a map, but it becomes a severe hindrance when working with critical assets. With more and more features like server authority being locked behind streaming, it’s important to give developers an escape hatch.
Unfortunately to make persistent models behave correctly in all situations, including when instances in the model have physics connections to parts outside the model, we can’t make persistent models replicate the same as in non-streaming experiences. For this reason you can’t rely on the join completion and must use the persistent loaded signal to ensure that persistent models have been replicated.
It’s more than initial replication on join–any model that gets parented to the workspace at any time is streamed in asynchronously. It is impossible to guarantee anything has replicated by the time a remote is sent or received on both network sides, which forces us either create our own replication systems or just not use streaming.
“Just wrap everything with WaitForChild and observers” is not a good solution. It’s like if instead of RemoteEvents you had to long-poll RemoteFunctions to receive all of your network signals. It’s very awkward and easy to create race conditions this way, and we can do better when model replication is reliable.
I don’t understand the problem with models having external connections. If a model is connected to something not streamed in yet, then I would expect that thing to also immediately steam in. Sure, this could result in stuff pathologically never streaming out, but isn’t that the point of persistent models, to opt-out of streaming? I’d rather have to diagnose performance problems than have a client crash from something not loading in on time.
Streaming is nightmarish to work with and it’s unfortunate that upcoming features are increasingly requiring it. So many edge-cases to account for, it would work so much better if we could just selectively enable streaming on specific models and have everything else function normally.