Is it worth the effort to transfer from DataStore2 to ProfileService?

I’ve heard great things about ProfileService and I’ve been wanting to use it for a while now but since I’ve already written a lot of code with DataStore2, I’ve been hesitant on doing so.

I currently trust DataStore2 more than ProfileService but since item duplication is a major problem in DataStore2 (from what I’ve read) and ProfileService is “item duplication safe”, it might be the best for my game since my game heavily relies on the economy and having a duplication glitch can ruin the experience for most players.

What are your thoughts? Should I switch over to ProfileService or should I create a session-locking system with DataStore2 (if that even is possible)?

7 Likes

Do you plan on having a trading system? If not then you can stick with Datastore2, but if you are planning on having one you can either mod Datastore2 to fix item duplication or use the Profile service.

I do plan having a trading system. How would I counter item-duplication though? Should I make sure that all saving has been done before the player can join back?

From my knowledge the ProfileService stops item duplication by only using the UpdateAsync function, so it does not use GetAsync or SetAsync. On the webpage I linked you see the part where it says:

In cases where another game server updated the key in the short timespan between retrieving the key’s current value and setting the key’s value, UpdateAsync() will call the function again to ensure that no data is overwritten. The function will be called as many times as needed until the data is saved.

So i guess only using UpdateAsync will stop data from being overwritten while it is being saved thus preventing the item duplication issue, I could be wrong, I’m also in the process of making my own Datastore wrapper using both DS2 and the profile service.

@EncodedLua did a great job explaining this topic in his youtube video: https://www.youtube.com/watch?v=P5NuM0gPmew&t=923s, maybe they could shed some more light on the topic.

4 Likes

In DataStore2’s API, :Update() is noted to be bugged so using the API member might cause some issues.

From what I know, the issue is being caused due to the player rejoining the server fast enough where :GetAsync() fires before :SetAsync() from the previous session. Wouldn’t a cooldown between the time a player leaves and the time the player joins back fix this issue or is there something I’m confused about?

Yes that’s the reason why item duplication occurs, you will have to find some to way to implement a cross-server cool down, because remember players can leave and join new servers. I’m not sure if the messaging service would also suffer from the same delay of publishing a message, but that is the only feasible service you could use for the cool down system. Also, I’m talking about UpdateAsync not the DS2 wrapper.

2 Likes

:UpdateAsync() wasn’t in DataStore2’s API so I got a bit confused.

I honestly can’t think of any working way to implement cross-server cooldown. I guess I could use ProfileService for storing the os.time() the player left and if they pass the cooldown, I could use :Get() on DataStore2 but I’m not so sure if that would work.

in my case its just better to use another data store system than the both two a datastore system

like quenty’s datastore system

You know that both the ProfileService and Datastore2 uses roblox’s datastores right? They are just wrappers.

3 Likes

True. I really haven’t fully grasped the idea of datastores so sorry for the hiccups.

Does loading one key on a datastore load all of them? I was thinking about having one key meant for the cross-server cooldown and if they passed that, I would load in the key with the player’s data.

I would really love to use ProfileService but I still do not trust them as much as DataStore2. I might have to research more on both modules to get a good understanding which one’s benefits outweigh the other.

1 Like

they are both wrappers they just do different functions

but they still do GetAsync() and SetAsync()

Your still relying on datastores for storing the cool down time, so traffic will prevent the latest time from saving, thus still allowing the player to rejoin quickly.

The profile service only use UpdateAsync()

but it still uses datastore functions :wink:

it doesnt matter if you use any wrapper or what aslong as its best for you

Dungeon quest uses DS2 and had a issue with item duplication, it is now patched, but the original DS2 module is still susceptible to duplication glitches.

Your not getting my point they don’t only use GetAsync and SetAsync

2 Likes

I was thinking of “opening” and “closing” os.time() tables. Basically when a player joins in, a session is opened with their os.time() entry and when they leave, the table is closed with another os.time().

What I was thinking is that every time a player joins, if the table’s closing value is still nil (meaning it has not saved yet), it would yield until a value is set.

I’m still not sure if this would work though.

API calls can error. The reason why ProfileService waits about 80 seconds before “stealing” the session lock is because that should give the other server enough time to sort out the issues with any API errors. There’s still a possibility that it takes longer than 80 seconds for the previous server to sort out the errors. This is still the best and safest way to save player data in my opinion.

The reason why using :GetAsync and :SetAsync separately is bad is because you’re prone to 2x as many network errors as you are with using a single query to both fetch AND update your data. :GetAsync also has a lot of caching headaches that might interfere as well.

To answer OPs question, it’s really only worth it to switch if players in your game already found out how to duplicate items. I would highly advise to use this on all new games you make, but transitioning between data systems can create more issues than it solves if you do it incorrectly.

2 Likes

UpdateAsync doesn’t do much to prevent duplication. Little to nothing actually. Profile service features Profile Locking, which is actually what stops duplication. It’s impossible for ProfileService to not use GetAsync, as that’s the only way to get data without overwriting it.