Allow configurable attribute replication limits for Server Authority

As a Roblox developer using Server Authority, it is currently difficult to synchronize larger predicted simulation state through attributes because the current documented limits only replicate an attribute if it is among the first 64 attributes on an Instance, its name is at most 50 characters, and string values are at most 50 characters.

I would like Server Authority to support configurable attribute replication limits, both globally for an experience and per Instance/class where appropriate.

Requested controls:

  • Configure how many attributes can be replicated per Instance, instead of the fixed first 64.
  • Configure the maximum attribute name length globally and/or per Instance.
  • Configure the maximum string attribute value length globally and/or per Instance.

This would help games that need to synchronize larger state for predicted/server-authoritative systems without splitting data across awkward extra Instances, remote event based replication or compressing names and values into less maintainable formats. Even if Roblox still needs hard platform maximums for performance and security, exposing developer controlled limits within those bounds would make Server Authority more practical for larger combat, inventory, ability, vehicle, and custom simulation systems.

6 Likes

that would likely require them to make unique engine network resolution path, bloating size of the client and a lot worse because of how they pack data
Also lets be honest having this many attributes is the biggest red flag here in the codebase
Not only because its innefficient performance wise but also because what are you coding if you need this many attributes bro?

1 Like

I use a fully modular system where the same checks are used by both client and server. For example, my vehicles write over 300 attributes and weapons reach within the 200 count. This allows me to not constantly replicate over tables or specific updates to data as attributes their self are replicated already, and attributes are nowhere near causing a single bottleneck.

  • You use more memory without using attributes and to modify or fetch attributes is not at all costly when compared to replicating things over as remote events.

Here is an example of the data I write:
DA7.lua (15.9 KB)

Address by The Grand Optimizer

Many developers believe that server authority somehow changes the economics of data access.

It does not.

Attributes and tags have their place.

Editor integration.

Replication.

Metadata.

They excel at those tasks.

But when they become your primary runtime storage…

That is where efficiency begins to decline.

Store your gameplay state in your own data structures.

Use dictionaries.

Use ECS.

Design your architecture deliberately.

Remember:

Every unnecessary engine boundary crossing is another cost.

One lookup is irrelevant.

One million become architecture.

And never forget:

YOU write the game.

NOT abstractions.

If a technical limitation exists…

ADAPT. :vulcan_salute: LIKE A REAL DEVELOPER.

The machine owes you nothing.

The profiler shows no mercy.

Optimize or Be Optimized. :gear:

stop bloating up this real suggestion with fake slop. to clear up your wrongs:

Many developers believe that server authority somehow changes the economics of data access.

yes it does. attribute access is very expensive compared to normal property access. innately it’s slower just by virtue of call overhead, but that’s not even what makes it slower as a whole (not an engineer).

and then you end up funneling yourself into a state where you have to deal with average-case O(n) space complexity and that’s not even getting into cross-referencing, accessing the data, let alone restoring the data on-rollback. barring the non-sequiturs, the same limitations you experience with attributes you end up having to deal with in the same way but with a different guise. you’re still going to have to pack large datasets, and you’re going to have to keep track of the payload size when you’re snapshotting data to not blow up weaker devices (or lock up the main thread on restoration).


as someone that does use all of these tricks (and more), i still frequently have to worry about payload size and attribute count:

_airPack, _kdPack, and _stunPack are packed attributes responsible for 15 attributes. and by virtue of me having to pack these attributes, these are forcefully limited to bytes: maximum 255 for 8b and 65536 for 16b.

moving attributes means completely changing the implementation in the worst case; it entails having to move to managing snapshots which therefore means figuring out how to implement reconstruction for what depends on live attribute state (e.g. per-frame runners) and also managing space and compression.

the problem isn’t just doing it. the problem is doing it safely, without regression, and while also limiting negative performance tradeoffs.


unfortunately, i’m thinking of the infrastructural changes that make this difficult. hosting rollback is essentially hosting a “micro” streaming service per authoritative-server (which roblox has a lot of). on the average case (for my game), i’m sending 30-40KB/s and receiving about the same and this will only scale with the amount of simulated objects (and scripted simulated objects) there are, which that scaling is also scaled by the amount of per-player network artifacts which require a back-and-forth “how about now? am i correct?” communication between the client and the server. that is a lot, the average fighting game takes about 20-50KB/s and they’re simulating just two entities on a battlefield. how does that scale with an environment where the world itself can mispredict? in my eyes: far too much, far too fast. in a lossless environment, that’s really hard and likely impossible.

but at the end of the day, i’m not an engineer. so i could be wrong. but logistically, it seems disproportionately tough.

???


Source and benchmarks, please, or argument instantly denied.


STOP Obfuscating your clear not understanding of dictionary algorithms with that many buzzword.
I’m not sure what you’re referring to with O(n) space here. Could you explain which data structure incurs that cost? A dictionary lookup is expected O(1), while total storage scales with the number of entries regardless of whether the values are attributes or packed data.


Please stop obfuscating basic bit-level operations as something complex.


That’s not how any of that works.
Numbers are F64, and you can safely write 53 bits of them in Luau, so where you get all these numbers is a mystery.* :red_question_mark:
* Unless it’s something very specific, then you could be limited to the I24 or I32 range due to roblox serializing it weirdly


Discussing the reast

That’s a hell of a lot of attributes on the image, and I don’t see any real data packing visible
That’s a lot of strings that could’ve been made into just number identifiers.
If you are struggling so much with that, you can just use binary strings and set them as attributes in case you need rollback to work correctly
I also don’t understand why you use UUID here because it’s just… bloat or something way too specific to be an attribute anyway

Also, Roblox will most likely treat all of them as 64 float numbers, so you are better off packing all 53 bits into a single attribute if you really need this rollback
The real problem is roblox being opaque as to how (and when) they sent all stuff over the network

attributes are not inherently laggy. it’s the replication of the attributes that makes them laggy. if you set attributes in-studio in bulk, you will not experience it.

here’s your benchmark: go ahead and set 6 attributes on a few hundred parts, or 64 attributes on about ~100 parts. playtest, go server-side, select that group, and then cut and paste it. observe your studio lag. now think about people who create heavy VFX using VFXForge.

I’m not sure what you’re referring to with O(n) space here. Could you explain which data structure incurs that cost? A dictionary lookup is expected O(1), while total storage scales with the number of entries regardless of whether the values are attributes or packed data.

yes, O(n) space complexity. it depends on the length of your snapshot buffer (which can be dynamic with respect to the average ping. many games describe this as “rollback frames”) and the size of the data you’re actually storing. it especially applies if you have dynamic systems or some form of transient state like knockback or projectile motion. it’s not constant and it never will be - especially with the compounding because that’s what rollback is.

Please stop obfuscating basic bit-level operations as something complex.

i particularly said “you’re going to deal with the same limitations with snapshotting as you will with attributes,” nothing about complexity. unsure how you got that lol

That’s not how any of that works.
Numbers are F64, and you can safely write 53 bits of them in Luau, so where you get all these numbers is a mystery.* :red_question_mark:

did not say that, but that’s exactly why i said what i said, and that’s why this request is valid. i have to pack multiple attributes into one solely BECAUSE numbers are f64. that adds up per-attribute. what would be four numbers instead need to be one attribute because storing them independently would be ~32B of data. 8B is a lot smaller than 32B.

the same thing goes for strings, too. if you separate attributes into different strings, you now have to store a new string for the attribute id and another for the attribute value. it’s the same real problem but as a number format. i too encounter this same problem with string lengths, and realizing that i couldn’t consistently apply more specific data about hit events to the entity (e.g. via JsonEncode)

i don’t care what qualifies as “real packing.” the point was to show that this is a real request that is potentially(?) solvable. i’m not going to flex what goes on in my game to prove a point that doesn’t matter. a lot of these attributes could’ve been cohesed into chunks instead of me having to essentially flatten my data.

That’s not binary strings; that’s a JSON format, which should be avoided at any cost.

By “real packing,” I refer to understanding data layout optimization instead of bloating it with “developer convenience”

Then why don’t you just pack all booleans and some numbers into a single attribute?
You contradict yourself

Just dont?
I never use any middleware they misname as “frameworks” so it’s not an issue I will ever get.
Always were and will be against this as well as against the script balkanization cult.

Exactly
Because they are not determenistic
You can’t really represent them as static numbers because replication will have to replicate the whole name because they can’t be mapped, although I have some sort of idea as to how this can be prevented for optimization; will make a feature request ig.