What better ways are there to storing user data in a DataStore?

I fought a lot for the usefulness and merit of UpdateAsync in the thread that @Operatik posted.

While there’s a lot to talk about in regards to the use of either function, one key difference I can pull out is that SetAsync may potentially be unreliable. GetAsync caches, so that means that what you push from SetAsync may not necessarily be what comes out from a GetAsync call. UpdateAsync does not cache and provides a live value to be used as the sole argument in transformFunction.

This all being said, you should probably be fine the way you’re using SetAsync and your current data set. I don’t think you need the previous value and hopefully you aren’t calling GetAsync too frequently either (or really at all aside from first load or where necessary).

I really do encourage you at some point in the future to move over to storing data via ModuleScripts as instances can become costly once attached to the DataModel. Modules are very handy once you get the hang of how to implement them. Writing them is not hard, but determining best practices on a case-by-case scenario is where you’ll find most effort will be put into.

On wiki it states that SetAsync can be hazardous because it overwrites data, UpdateAsync is a much safer method as it updates not overwrites data, personally I’ve experienced a ton of dataloss issues with SetAsync and I’ve just recently switched to UpdateAsync.

For player data, when the player leaves, the data could be completely different (and usually will be). I don’t see any reason to compare new and old values when the new value could be completely different. Of course, you should do checks to make sure all your data’s there before you save, but you don’t have to use UpdateAsync to make sure what you’re saving isn’t nil.

Well you see, the whole point of UpdateAsync isnt about comparing 2 values, thats just a bonus, what it’s really about is updating data not over writting it, much harder to lose data that way.

1 Like

From what I understand, UpdateAsync is basically like a version history system. What @Complextic is saying is that UpdateAsync will basically cache the old value. If there is no old value, the code won’t fail, there will just be no old value to cache. SetAsync doesn’t do this, it only overwrites the value. The reason UpdateAsync is important is because if it were to fail, it can always fall back on the old value which prevents complete data loss. Having 90 points on the leaderboard instead of 100 points is better than losing all of your points.

Yeah thats basically the entire point behind UpdateAsync is if it cant make a new save instead of losing all of the data it will have the previous data it can fallback on.

Not necessarily. UpdateAsync isn’t remotely like a version history. It simply passes a non-caching value to transformFunction, that value being what the DataStore key currently has entered.

Code can still fail, regardless of whether you have a value assigned to a key or not. Either the data assigned to a key will be passed as oldValue or nil in the case of no value.

Depending on how you use UpdateAsync, you can experience the exact same data loss that you do with SetAsync.

Also, surprisingly, some tests last night after a discussion on UpdateAsync revealed interesting behaviour. It depends on what kind of failure you’re talking about.

As far as transformFunction goes, if you pcall UpdateAsync and transformFunction fails, transformFunction will throw an error but pcall will actually return success and nil. Depending on if you use the return from UpdateAsync, this could be detrimental.

You are way more likely to experience dataloss with SetAsync than you are with UpdateAsync and I speak from experience.

I’m not sure how it’s “much harder to lose data” with UpdateAsync. The only benefit I can see with UpdateAsync is if you’re saving the old data to another place or don’t check if the value you’re setting is nil. If there’s any other benefits that make it easier not to lose data, I’d be much more interested in using it. I just don’t see any major benefits.

I mean it literally says it in the screenshot above that SetAsync() can be hazardous.

Yes, but it doesn’t explain at all why. In the case of user data, you don’t necessary need to consider the old value; if the user’s in the server, the values you have been using in that server should be correct anyway.

It is hazardous because it overwrites data, meaning it completely erases the old data that was there previously.

Yes, why do you care about the old data? That’s what I have been asking the entire time.

We care about old data because if the SetAsync() errors then all the data is lost, but if it errors with UpdateAsync() the old data was not erased so it has something to fallback on.

Where does it say that on the wiki? None of the error handling pages on datastores say this.

That is completely irrelevant. If the SetAsync errors, it makes no sense for it to delete the data. If it can’t access Roblox servers, how would it delete the data?

I don’t know what to tell you at this point. All I can tell you that my game experienced a lot of data loss issues with SetAsync() and I switched to UpdateAsync() and I havn’t had the same data loss issues.

Other people are also saying exactly what I’m saying:

1 Like

(Taking the post that is saying to use UpdateAsync, rather than the few that aren’t.)

It looks like they’re talking about when you’re using multiple scripts to access to same datastore, which makes sense. I agree with using UpdateAsync in that case, thanks for linking these threads.

Np sorry for the bad discussion I’m really bad at explaining things

1 Like