The three scopes
strongest
The same real object yields the same
localId after a full server restart on the same
map, and that id is never reissued to a different object.It must come from something the host system itself durably stores: a SQL primary key, a
persisted monotonic counter, a config key. Not something Vetra computes, and not something
derived from the object’s current state.Only persistent domains can be honestly restored across a restart.Unique and stable while the server process runs. A restart may invalidate or reissue it.Correct for anything held only in memory: a runtime-spawned prop, an NPC. It is not a
lesser answer, it is a different and often true one. Blueprints handles it correctly: a
restore across a session boundary reports the affected members as cross-session rather than
matching them by luck.
last resort
No uniqueness or stability guarantee. Legal, reported loudly, and effectively excludes the
domain from safe restore.If you find yourself reaching for it, the answer is usually that identity should be added to
the addon being integrated, not worked around here.
Declare the weakest you emit
The descriptor’sidentity = { scope = ... } is a floor:
session even though map-baked props are genuinely
persistent, because runtime-spawned ones are not, and the floor has to hold for every record.
The prohibition
The pattern that works
An adapter-owned durable key. The host system already assigns one; map it straight through.AUTOINCREMENT column does not. An array index into a table that gets compacted very
much does: an index is a position in a list, not an identity.
Good and bad, concretely
1
Add one to that addon
A persisted counter is four lines.
2
Declare session, and say so
Correct for genuinely in-memory state.
3
Declare weak
And accept that the domain is captured but not restored.
source, and what it is for
source is diagnostic. It describes where the id came from and gates nothing; scope is
the guarantee, and it is the field the engine actually reads.
Materialize creates a NEW identity
Reusing it would make a migration’s target indistinguishable from its source, and a restore would then reconcile one against the other.The principle, in one line
The source describes desired state. The destination owns destination identity.This runs through migration, cross-server deployment and restore alike. It is why a deployment maintains an explicit source-to-target mapping and why a source id that is not in that mapping resolves to nothing, never to itself. Row ids and map creation ids are numbered from the same 1 on every server. An id that fell through would address a real object on the destination that has nothing to do with the one being deployed, and
Remove does not ask where its argument came from.