As a Roblox developer, it is currently too hard to move a model out of Workspace temporarily and bring it back without clients ending up with an incomplete copy.
The problem
Placing an Atomic model under ReplicatedStorage does not guarantee atomic replication. In practice this means:
- The server moves an Atomic model from Workspace into ReplicatedStorage. For clients that didn’t have it streamed in, it now replicates through regular replication, and its descendants can arrive over several frames.
- The server (or a client script) moves it back into Workspace. Client code that runs on stream-in or on ChildAdded can see the model before its PrimaryPart or other descendants exist. That happens even though the model is marked Atomic and is now back in Workspace.
The result is PrimaryPart being nil, missing children, and WaitForChild spread across code that Atomic was supposed to make unnecessary. The docs even list “minimize use of WaitForChild()” as the reason ModelStreamingMode exists.
Why current workarounds aren’t enough
- ServerStorage restores atomicity when the model returns to Workspace, but clients can’t read it while it’s stored. The client-side Instance is also recreated, so any client state keyed by that instance is lost.
- Hiding in place (transparency, collisions, attributes) keeps the model in Workspace. But that means manually toggling every part, light, emitter, sound and prompt, and restoring their original values.
- Custom completeness checks (stamping a descendant count and polling on the client) work, but every developer has to reinvent them. They also have to take into account any changes to the model, which is almost impossible to predict in project with many scripts and mechanics.
Proposed solution
When a Model with ModelStreamingMode = Atomic (or Persistent) is replicated to a client, send the model and all of its descendants as one unit, regardless of which replicated container it’s in. That would cover being parented into ReplicatedStorage, being reparented between replicated containers, and moving from ReplicatedStorage back into Workspace. At minimum, a client should never observe an Atomic model in the DataModel before all of its initial descendants are present.
If changing Atomic’s behavior outside Workspace is undesirable, an alternative would be:
- a separate property (e.g. Model.ReplicateAtomically), or
- a signal or method that tells the client when a replicated model’s subtree has fully arrived (something like Model.ReplicationCompleted or Model:WaitForFullReplication()).
Impact
If Roblox is able to address this, it would improve my development experience because I could rely on Atomic as a real guarantee instead of adding custom descendant-count checks and layering WaitForChild calls (which I was avoiding until late in development when I realized this current issue, which not only breaks the game for random people, but spams the console with irrelevant errors). That would remove a whole class of intermittent, hard-to-reproduce “missing PrimaryPart” bugs that only show up under real network conditions. I’ve reported having issues with Streaming which only now turned out to be my mistake of not understanding the impacts of the incomplete behavior of atomic models. Here is the post: Atomic models are not fully atomic