Save your player data with ProfileService! (DataStore Module)

Yup. ProfileService uses one key per profile, so it’s going to be compatible with Roblox’s own versioning systems.

2 Likes

Didn’t get any reports so far for data loss with ProfileService.

6 Likes

hi, first off, I love your module! :grin: It is very intuitive and well made. Secondly, is there a way to detect changes to certain values such as a .Changed equivalent?

1 Like

Since ProfileService is not a change signal provider, you’ll either need to create your own get / set interface or simply update Profile.Data when your value object triggers .Changed

Wow! You’ve successfully sold this to me (thanks for making it Open Source by the way)! I’ve used DataStore2 for a while, and as it seems that Ordered Backups are soon no longer going to be necessary whenever the new API changes happen. This is part of my reasoning behind switching to ProfileService. Most of the things DataStore2 offers that ProfileService has I am fine writing by myself and would prefer to do that anyways (serialization, etc).

My only question is about detecting issues with Roblox’s datastores. DataStore2 has :IsBackup() which appears to work in most cases (but not in the last incident it seems). This just means that the current store is a temporary one and does not save at all to prevent issues. How does ProfileService specifically react to datastore saving issues like the recent one (does it return nil, etc), and is there anything else you would recommend for handling events like this (especially with regard to Robux purchases)?

Thanks!

1 Like

ProfileService basically IS the module that handles DataStore issues, given the developer has properly understood the documentation for the module.

Developer product purachase callbacks should be confirmed only when you know the player data has been saved - this can be done by utilizing Profile.MetaData.MetaTags and Profile.MetaData.MetaTagsLatest - see documentation for more info about them.

1 Like

Ah. Thanks for the specifics on MetaTags. From how I understand it, if the datastore itself fails to load, the profile will return nil. DataStore2 allows you to set a max number of tries and specifically informs you if it cannot load the data. From my understanding, ProfileService returns nil and to notify players of issues I should use the critical state signal.

If for some reason datastores are completely failing and ProfileService cannot access saved profile information, it would simply return nil. Please correct me if I am wrong.

However, you listed Kicking the player as the best option for when :LoadProfileAsync() returns nil. If datastores are down, wouldn’t the players automatically get kicked upon joining the server?

The specific case that I am seeking to answer is about notifying players that their data is having issues saving and loading, and notifying them when they join (and letting them join) instead of kicking them.

How would I go about doing this, and do I understand this fully or is there something I am missing?

P.S. Thanks for the quick reply on purchases. You have been very helpful.

EDIT: It seems that it will load indefinitely. I apologize for not seeing that you already answered my question. I will be building this eventuality into my handler. Thanks again for the module!

Quick question: does ProfileService encrypt data, and if not, would this be something worth doing myself? I saw something else do it a while back and am wondering if it would be something I would want to do.

Do you mean encrypting or encoding? Encrypting shouldn’t be necessary because you shouldn’t be storing confidential information about players in DataStores. Encoding also shouldn’t be necessary since the character limit is around 4 million now, and even a good building system would have trouble reaching that.

1 Like

I take it this only means stuff you wouldn’t be putting on Roblox anyway (real name, phone number etc)?

1 Like

Seems more efficient than DataStore2. Will ProfileService be getting any new functions? I’m planning it to use it for upcoming game.

ProfileService might receive rollback management in the near future

5 Likes

Nevermind! I figured out the issue.

The fact that DataStore2 is bound to the Player instance was a deal-breaker for me. Will be sure to use this once I start implementing saves.

3 Likes

Really great resource, really great. The fact that DS2 is overrated makes this profile service is better

1 Like

Hey! If we are making an RPG for example will we have to script the update of data manually?

For Example: A player first plays a game and gets the default table. I now update the game and add a few more items. Is there a function to update the player’s data (so id have to add these items to the data) or will I have to script that myself?

This is a truly great module, thank you very much for this @loleris! I was using Datastore2 primarily for its backup capability and its caching, but ProfileService is a must-have. I watched the posted tutorials, read all the comments here and in the videos, looked over the API, and skimmed over the code… and I am switching over today. These were the reasons I didn’t 100% like Datastore2 which are nonexistent with ProfileService:

  • Stored data on the player instance (this causes some future-related problems)
  • Massive amounts of redundancy when saving player data which will never be used
  • This Roblox mistake left Datastore2 developers in a bad position.
    • If I recall correctly, if a player didn’t log back in within a certain time, then their savefile was deleted. Since saves are tied to player instances then accessing the data was…problematic
  • No protection against duplicated items
    • I plan to implement trading and knew duplication would be a problem. My initial plan didn’t involve session-locking and probably would’ve failed as a result.
  • No built-in autosave
    • You need an autosave in case a player has played in the same server for an hour, then that server crashes. Then what? That player will probably quit your game, even if they loved it, because of the wasted time. I created one myself and had to work out some quirks to get it working the way I wanted…this is another big point to switch over since it’s built-in.

I’m impressed by what ProfileService has to offer:

  • Item duplication protection
  • Data caching
  • Comprehensive API documentation with great examples
  • Built-in autosave that evenly distributes among players within the server + uses coroutines
  • Transparency with any caveats (very few)
  • Useful comments in the code that show expected table structures
  • Lots of analytics for those who like to read logs (I)
  • ProfileStore.Mock - Customize your datastore Testing
  • :Reconcile - Updating Datastores
  • DeepCopyTable - Handles nested keys
  • :GlobalUpdateProfileAsync - Allows the functionality of gifts or messages between players (even offline)
  • :WipeProfileAsync - GDPR compliance
  • :SetMetaTag - Updating profile information
  • AssumeDeadSessionLock - Automatically releases profiles if the session doesn’t update within 30 minutes
  • Enough information that answered every single question that I had
  • +Solves a ton of other issues

A truly high-quality datastore module, thanks again!

15 Likes

Is there a recommended way to tell the client when their data changes?

Currently, I do something like this with AeroGameFramework

-- SERVER
local profile = self:Get(player)

if (profile) then
    profile.Data.Cash += 50
end

-- Tell client their data changed
self:FireClient("DataUpdate", player, profile.Data)



-- CLIENT
local data = {}

DataService.DataUpdate:Connect(function(newData)
    data = newData or {}
end)
2 Likes

Can you not require the module on client? cuz it gave me an error saying BindToClose can only be called on the server. Stack Begin Script 'ReplicatedStorage.DataManager.ProfileService', Line 242

DataStoreService is a server-side only feature on Roblox, so ProfileService is server exclusive.

1 Like