Streaming Prefetch API and Improvements to Part Handling

This reminds me that I need to support streaming for my up coming game.
Thanks for making it easier and more controllable. :grinning:

1 Like

Amazing to see streaming finally getting some love :heart_eyes:

1 Like

@MrGreystone can you create a separate bug report on the streaming/rendering issue you are seeing? Rendering adjusts to CPU and memory load. We’d like to better understand what is going on in your situation.


They would need to explore the entire map to get the data, so it wouldn’t be nearly as easy. With server-side sanity checks to prevent teleportation, it would be very difficult to steal a huge map.

This sounds like a problem in itself, not a reason to give the client even more control. Servers really need to be capable of doing sanity checks for character positions to prevent teleport hacks; This is a big reason I made my game entirely local.

I don’t see why you can’t just set up a RemoteEvent that makes the server call instead; it would need to send the server that request anyways.

There’s also some level of privacy players will expect when playing future games that have massive maps. Exploiters being able to watch what people are doing on the other side of the map or in their private house area is just creepy. Most Roblox games have relatively small maps today, but we need to be mindful of the engine’s future.


@Tomarty hopefully the change to how local parts are handled fixes the main issue you were likely seeing with streaming enabled. If you think there are additional streaming bugs still causing you problems please file a bug report to let us know.

Thanks for raising the concern about allowing prefetch to be called from the client. There are limits in place to prevent the requests from causing more load on the server. We will discuss the potential security concerns that you raised about letting clients stream regions they shouldn’t get.


Can we at least have the option to change these with a Script?

Think of Minecraft Render settings, different people have different devices and preferences.

Exploring game mechanics, player can expand their Render distance for example.

This is like Lightning.Technology all over again, why can’t we change this stuff in game?

What’s the point of using this then?

I understand that from time to time things will fail but that’s not the issue here, could we at least have something to let us know that this failed so we can do something about it?

What kind of terrible UX would this present?

Imagine being teleported then falling to your death in a Rouge like game because your Internet is bad…

This even happens in Minecraft while Chunk loading, it’s very frustrating.


@RuizuKun_Dev the streaming radii aren’t meant for device specific performance tuning. Not every developer has a lot of devices for testing/tuning on, so our philosophy is that the Roblox engine should adapt automatically.

The point of using the prefetch is to avoid having to wait for regions to be streamed when the player arrives in the new location. As for preventing the player from falling to their death, that is what StreamingPauseMode is for. It is best to use the prefetch in combination with streaming pause. If the prefetch succeeds then when the player is CFramed and they continue playing without interruption. If the prefetch can’t request enough, or if the player arrives before the prefetch is finished, then they pause after the CFrame until the regions arrive.


What I had in mind was not exactly for Developers to fine tune the settings but the players will be instead, like Minecraft render settings.

I see, I must have misunderstood the text from DevHub

The “Graphics Mode” and “Graphics Quality” sliders are designed to serve that purpose in the client.


RE: using models to group parts together for streaming- are there plans for a streaming mode that allows entire models to stream in and out based on their primary part or bounding box position, instead of models being always streamed in, and only streaming individual child parts?

Currently, I handle client object lua initialization like this:

  • Client listens to CollectionService:InstanceAdded signals to detect models that need their lua objects to be initialized
  • Before the object can initialize, the rest of the object needs to be streamed in, so I use :WaitForChild or :ChildAdded or :DescendantAdded to yield for streaming neccessary parts. This comes with a stipulation that if the object model is streamed out or destroyed while I’m yielding for it descendants, we have to break out.
  • When everything is present, initialize the object on the client.

The problem, as documented here, is that because models are always streamed in, with thousands of models and all of them streamed in way before their actual children are streamed in:

  • there is an unnecessary amount of connections and coroutines running to yield for model children to stream in, consuming excessive lua memory
  • there is an unnecessary amount of models and non-basepart descendents streamed to clients before they are needed, consuming excessive instance memory

In my game and most cases, I’d like to be able to tell the engine that it’s safe to assume that each highest level model represents an object which should be collectively streamed in and out together and in its entirety, based only on the primary part position or the bounding box position. This makes it unambiguous for the client to know if an object is streamed in or not and if it’s ready to initialize, it cleans up unnecessary instances on the client, it cleans up client lua object initialization procedures, and it prevents half-streamed models.


@Defaultio we are discussing potential improvements to model handling, including atomicity, but I don’t have good solution for you currently.

We are working on improvements to how complex mechanisms a streamed in and out that may help you.


If you guys focus in your own servers upgrading it better than those are actually better, the servers can’t really handle games that have around 20k parts with 50 players…

Agree with Defaultio. It can be hard to deal with root Instances containing various parts, which are not streamed in and out on an atomic basis. This could lead to execution order edge cases. Also, marking applicable Instances as essential, i.e. that they should not be streamed out once streamed in and should be in sync with the server, would allow for incremental implementations of streaming over time for certain objects in Workspace, meaning a game can be produced faster and improved later if necessary. The local part changes only partially address this, as they can’t be natively synced with the server for physics.

If we have no control over what is streamed and what is not, it generally takes a lot of unnecessary time and frustration to design and debug components. I dropped streaming support on a work-in-progress game recently because of this and because of the performance impact. I think these capabilities are important for making streaming a viable option for most developers.

So parts have to be created on the client for streaming to not remove them?

One hack I was attempting to do was store parts under the ReplicatedStorage on the server and have the client parent them into the Workspace to decouple it from the streaming process, but unfortunately this doesn’t seem to work.

Is it at all possible to force a part from the server to be constant?


From my experience, this is pretty unreliable (although possible).
If you want to remove streaming issues, you unfortunately are forced to parent parts to a client.

If anyone is looking for a plugin to help with streaming development, I just announced my new Streaming Debugger over here :)!


@Maximum_ADHD if you clone a part in a local script then it will be considered a local part. If you reparent out of ReplicatedStorage into the workspace on the client it will be considered a remote part.

I used to change the player’s focus, but started using this instead, issue is… this doesn’t stream in everything around the new area and really barely streams anything :eyes:

Use case: spectating players in a different location far away.

1 Like

The prefetch is designed to only stream the minimum radius needed to prevent a pause when the player arrives, which is the minimum radius.

1 Like

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.