Source: Roblox Creator Hub · CC BY 4.0 · View source · Code samples: MIT Imported 2026-10-03. Formatting adapted for this site.
Instance streaming
In-game instance streaming allows the Roblox engine to dynamically load and unload 3D content and related instances in the Workspace. This can improve the overall player experience in several ways, including:
— Players can start playing in one part of the world while more of the world loads in the background.
— Games can be played on devices with less memory since content is dynamically streamed in and out. More immersive and detailed worlds can be played on a wider range of devices.
— Better frame rates and performance, as the server can spend less time and bandwidth synchronizing changes between the world and players in it. Clients spend less time updating instances that aren't currently relevant to the player.
— When configured, distant models, platform avatars, and terrain remain visible even when they're not streamed to clients, keeping the game optimized without entirely sacrificing background visuals. SLIM provides the highest-fidelity level of detail for both models and avatars.
Instance streaming is controlled through the Workspace.StreamingEnabled property, enabled by default for new places created in Studio. This property cannot be set in a script.

Note
Once you review this technical guide, it's recommended that you review the streaming techniques guide on how to use streaming efficiently and effectively, and the SLIM guide for enabling high‑fidelity level‑of‑detail on models and avatars.
Technical behavior
Scope
Streaming logic and features apply exclusively to instances that are descendants of Workspace, while instances stored in other containers such as ReplicatedStorage and ReplicatedFirst are ineligible for streaming. For example, placing an atomic model under ReplicatedStorage does not guarantee atomic replication.
Stream in
When a player joins a game with instance streaming enabled:
- Instances in the
Workspaceare replicated to the client excluding the following:
[`BaseParts`](/docs/basepart) ([`Parts`](/docs/part) and [`MeshParts`](/docs/meshpart)) [`Models`](/docs/model) set to [Atomic](#atomic), [Persistent](#persistent), or [PersistentPerPlayer](#persistentperplayer); see [per‑model streaming controls](#model-streaming-controls) [`Models`](/docs/model) set to [Nonatomic](#nonatomic) (default) when [`Workspace.ModelStreamingBehavior`](/docs/workspace#workspace-modelstreamingbehavior) is set to [`Improved`](/docs/enum-modelstreamingbehavior#improved) Descendants of the above instances - During gameplay, the server may stream instances in the above deferred categories to the client based on the game's streaming properties, player position, client device performance, and other conditions.
Stream out
During gameplay, a client may remove regions of BaseParts from the player's Workspace based on the behavior set by Workspace.StreamOutBehavior. The process begins with regions furthest away from the replication foci and moves in closer, as needed. Regions inside the Workspace.StreamingMinRadius range never stream out.
Note that a Model with no BasePart descendants, such as one used merely as a "container" for non‑BasePart instances like scripts, is exempt from streaming out unless it is made a descendant of a BasePart.
Note
Instances which are created or cloned by client-side scripts are exempted from streaming out unless they are parented under a server‑created instance.
Note
When an instance streams out, it is parented to nil so that any existing Luau state will reconnect if the instance streams back in. As a result, removal signals such as ChildRemoved or DescendantRemoving fire on its parent or ancestor, but the instance itself is not destroyed in the same sense as an Instance:Destroy() call. Local-only changes to instance properties (changes that exist on a client and have not been replicated to the server) can be lost if the instances streams out and later streams back in.
Assemblies
Physical assemblies stream in as complete units, including their associated Constraints and Attachments, helping to ensure consistent physics updates on clients. The only exception is when the assembly is anchored, in which case only the BaseParts within the streaming radius are streamed in alongside their associated Constraints and Attachments.
Assemblies do not stream out until all of their BaseParts are eligible to stream out.
Note
Avoid creating moving assemblies with unnecessarily large numbers of instances, as all of the instances streaming in unison may cause network/CPU spikes.
Streaming properties
The following properties control how instance streaming applies to your game. All of these properties are non-scriptable and must be set on the Workspace object in Studio.

| Property | Description |
|---|---|
| [`EnableSLIMAvatars`](/docs/workspace#workspace-enableslimavatars) | Controls whether a [SLIM](https://create.roblox.com/docs/workspace/streaming/slim#enabling-slim-for-avatars) model is generated for avatar characters in the game. When enabled, avatars render using SLIM in the same way that setting [`Model.LevelOfDetail`](/docs/model#model-levelofdetail) to [`SLIM`](/docs/enum-modellevelofdetail#slim) works for other models. See [SLIM](/docs/roblox-workspace-streaming-slim) for details. |
| [`ModelStreamingBehavior`](/docs/workspace#workspace-modelstreamingbehavior) | Controls how [Nonatomic](#nonatomic) (default) models stream in and out. Use [`Improved`](/docs/enum-modelstreamingbehavior#improved) to enable the most efficient streaming for [`Models`](/docs/model) with [`BasePart`](/docs/basepart) descendants. |
| [`PredictiveStreamingMode`](/docs/workspace#workspace-predictivestreamingmode) | Opts in to [predictive streaming](#predictive-streaming) which uses engine signals to proactively stream areas a player is likely to need soon, such as respawn locations or regions the player recently left via [`CFrame`](/docs/cframe) change. Predictions are additive, expire after a short time if unused, and are skipped on resource‑constrained clients. |
| [`StreamingIntegrityMode`](/docs/workspace#workspace-streamingintegritymode) | The game may behave in unintended ways if a player moves into a region of the world that hasn't been streamed to them. This property offers a way to avoid those potentially problematic situations. Use [`PauseOutsideLoadedArea`](/docs/enum-streamingintegritymode#pauseoutsideloadedarea) to balance gameplay integrity without pausing unnecessarily or too often. You can also [customize the pause screen](#pause-screen-customization). |
| [`StreamingMinRadius`](/docs/workspace#workspace-streamingminradius) | This property indicates the radius around the [replication foci](#replication-focus) in which instances stream in at the highest priority. Care should be taken when increasing the default, as doing so will require more memory and more server bandwidth at the expense of other components. Use the default of `64` to maximize how much the engine can scale the game down for low‑end devices. |
| [`StreamingTargetRadius`](/docs/workspace#workspace-streamingtargetradius) | This property controls the maximum distance away from the [replication foci](#replication-focus) in which instances stream in. Note that the engine is allowed to retain previously loaded instances beyond the target radius, memory permitting. A smaller [`StreamingTargetRadius`](/docs/workspace#workspace-streamingtargetradius) reduces server workload, as the server will not stream in additional instances beyond the set value. However, the target radius is also the maximum distance players will be able to see the full detail of your game, so you should pick a value that creates a nice balance between these. Use the default of `1024` to strike a good balance between visibility for players on high‑end devices and a reasonable memory footprint. |
| [`StreamOutBehavior`](/docs/workspace#workspace-streamoutbehavior) | This property sets the [streaming out](#stream-out) behavior according to the value of [`StreamOutBehavior`](/docs/enum-streamoutbehavior). If set to [`LowMemory`](/docs/enum-streamoutbehavior#lowmemory) (default), the client only streams out regions beyond the minimum radius in a low memory situation. If set to [`Opportunistic`](/docs/enum-streamoutbehavior#opportunistic), regions beyond [`StreamingTargetRadius`](/docs/workspace#workspace-streamingtargetradius) can be removed on the client even when there is no memory pressure (in this mode, the client never removes instances that are within the target radius, except in low memory situations). Use [`Opportunistic`](/docs/enum-streamoutbehavior#opportunistic) to allow the client to aggressively garbage collect content, significantly reducing memory usage and helping prevent out‑of‑memory crashes. |
Note
StreamingTargetRadius should be larger than StreamingMinRadius. 3D content between the target radius and the minimum radius acts as a buffer in case the client temporarily stops receiving new content from the server. If the minimum radius and the target radius are equal, there is no buffer, which can lead to an increase in network pauses or an otherwise suboptimal player experience.
Replication focus
By default, streaming occurs around the local player's character's PrimaryPart, although you can specify a different replication focus point through Player.ReplicationFocus.
You can also add and remove additional replication foci through Player:AddReplicationFocus() and Player:RemoveReplicationFocus() to dynamically enable streaming in multiple areas of the game.
Note
Use caution when adding additional replication foci as each additional focus increases the server's workload for streaming and updating regions. For example, a single player with nine dynamically moving foci could generate server networking and streaming processing comparable to ten players moving around the game.
On the client, too many foci for a player can limit the engine's ability to adjust to memory limitations and make it more likely for clients to be killed by the OS for using too much memory.
Physics Simulation
Client-side physics simulation, including prediction and resimulations when server authority is implemented, only occurs in streamed areas, even for locally created instances and for Persistent instances. If you have instances that you'd like to keep simulating even when they're far away from the character, create an additional replication focus near those instances.
Movement Between Zones
In many games, players frequently move back and forth between the same areas, for example between their "home base" and a "trading hub." In such cases, you can create a replication focus point in each area to ensure those areas are readily present on client devices.
Distant Viewpoints
Multiple replication points are useful when players can view specific, important regions through a scope, such as enemy bases scattered across a barren landscape. In such cases, you can create a replication focus point in each base to ensure players see details and simulated physics from afar.
Predictive streaming
Predictive streaming is an opt‑in feature that uses engine signals to anticipate player movement and proactively stream areas the player is likely to need soon. When enabled by setting PredictiveStreamingMode to Enabled, it can reduce streaming pauses and visual pop‑in without any code changes.
Predictive streaming is additive. It creates small, temporary streaming foci in addition to your existing replication foci, streams a small amount of extra content, and does not change your game logic or streaming contracts. If a prediction isn't needed, the predicted area expires after a short time and the engine unloads the content. The engine also takes client memory and performance into account, skipping predictions on resource‑constrained devices.
When PredictiveStreamingMode is Enabled, the following predictive features are active:
| Feature | Description |
|---|---|
| Spawn pre‑fetching | When a player dies, the engine creates small, temporary streaming foci at possible spawn locations so that likely respawn areas begin streaming before the player character appears, reducing pauses and missing content immediately after respawn. |
| [`CFrame`](/docs/cframe) return optimization | When a player [`CFrames`](/docs/cframe) away from an area, the engine creates a small, temporary streaming focus at the location they left. This helps keep that area streamed in if the player returns shortly after, a common scenario when moving between buildings, sublevels, shops, or hubs. |
Note
Predictive streaming works seamlessly with manually created pre‑fetches (Player:RequestStreamAroundAsync()) and multiple replication foci (Player:AddReplicationFocus()). If you've already created a pre‑fetch or replication focus at a specific location, predictive streaming does not add another streaming focus there.
Model streaming controls
To avoid issues with streaming on a per-model basis and minimize use of WaitForChild(), you can customize how Models and their descendants stream through their ModelStreamingMode property.
Nonatomic
By default, models are Nonatomic and they stream in/out based on whether Workspace.ModelStreamingBehavior is set to Legacy (default) or Improved.
Legacy
When Workspace.ModelStreamingBehavior is set to Legacy (default), the Model container and its non‑BasePart descendants such as Scripts replicate to the client when the player joins. Then, when eligible, the model's BasePart descendants stream in.

Improved
When Workspace.ModelStreamingBehavior is set to Improved, model streaming behavior varies by whether the model contains BasePart descendants or does not contain BasePart descendants:
A model with
BasePartdescendants streams in only when one of itsBasePartdescendants is eligible to stream in. At that point, the model and the eligibleBasePartstreams in, along with the model's non‑BasePartdescendants.When the very last remaining
BasePartof the model streams out, the model itself will stream out along with it.
A model with no
BasePartdescendants, such as one used merely as a "container" for non‑BasePartinstances like scripts, replicates to the client soon after the player joins. This type of model is exempt from streaming out unless it is made a descendant of aBasePart.
Atomic
If a Model is set to Atomic, all of its initial descendants are streamed in together when a descendant BasePart is eligible to be streamed in. As a result, a client‑side script that needs to access instances inside the model would need to use WaitForChild() on the model itself, but not on a descendant MeshPart or Part since they are sent alongside the model.
An atomic model is only streamed out when all of its descendant parts are eligible for streaming out, at which point the entire model streams out together.

Persistent
Persistent models are not subject to normal streaming in or out. They are sent as a complete atomic unit soon after the player joins and before the Workspace.PersistentLoaded event fires. Persistent models and their descendants are never streamed out, but to safely handle streaming in within a client‑side script, you should wait for the PersistentLoaded event to fire.

Note
Persistent models are intended for very rare circumstances, such as when a small number of parts must always be present on clients for client‑side scripts to access. If possible, server-side Scripts should be used, or client scripts should be tolerant of parts streaming in and out. Persistent models are not intended to circumvent streaming, and overuse may negatively impact performance.
PersistentPerPlayer
Models set to PersistentPerPlayer behave the same as Persistent for players that have been added using Model:AddPersistentPlayer(). For other players, behavior is the same as Atomic. You can revert a model from player persistence via Model:RemovePersistentPlayer().
Pause screen customization
Assuming Workspace.StreamingIntegrityMode is set to the recommended PauseOutsideLoadedArea, the game will pause if a player moves into a region of the world that hasn't been streamed to them. In these cases, the Player.GameplayPaused property indicates the player's current pause state which can be used with a GetPropertyChangedSignal() connection to show or hide a custom GUI.
local Players = game:GetService("Players")
local GuiService = game:GetService("GuiService")
local player = Players.LocalPlayer
-- Disable default pause modal
GuiService:SetGameplayPausedNotificationEnabled(false)
local function onPauseStateChanged()
if player.GameplayPaused then
-- Show custom GUI
else
-- Hide custom GUI
end
end
player:GetPropertyChangedSignal("GameplayPaused"):Connect(onPauseStateChanged) Runtime debugging
The engine includes multiple on-screen debug panels that can be enabled on the client using keyboard shortcuts. To access streaming debug information:
- Open the Network Summary debug overlay via ShiftCtrlF3 (Windows) or Shift⌘F3 (Mac).
- Once the debug overlay is open, press Shift1 repeatedly to cycle through the available panels. The fourth panel is the Streaming debug view which displays useful runtime information:
- Active streaming settings
- Currently loaded (streamed in) regions
- Streaming behavior and state
Once enabled, colored highlighted regions appear in the 3D viewport:
| Color | Description |
|---|---|
| Less than [`StreamingMinRadius`](/docs/workspace#workspace-streamingminradius) | |
| Greater than or equal to [`StreamingMinRadius`](/docs/workspace#workspace-streamingminradius) and less than [`StreamingTargetRadius`](/docs/workspace#workspace-streamingtargetradius) | |
| Equal to [`StreamingTargetRadius`](/docs/workspace#workspace-streamingtargetradius) | |
| Greater than [`StreamingTargetRadius`](/docs/workspace#workspace-streamingtargetradius) |
Note
To increase the ability to zoom the default camera considerably far out while debugging, temporarily increase StarterPlayer.CameraMaxZoomDistance while in edit mode or Player.CameraMaxZoomDistance during runtime. A value of 1000, for example, allows you to pull the camera out to view most of the 3D world while still navigating the character around.