Save your player data with ProfileService! (DataStore Module)

DATA STORE v2 IS NOW SUPPORTED - Click for more info

Mad Studio cross-promo:

Check out ReplicaService for state replication / networking!
If you’re curious about how Madwork is written, give MadLife - code_guidebook a read!


If you find this resource helpful please consider supporting me by shouting out my latest project :smiling_face_with_three_hearts:


Madwork - ProfileService

ProfileService on GitHub

ProfileService is a stand-alone ModuleScript that specialises in loading and auto-saving
DataStore profiles.

It’s documented:
ProfileService wiki

It’s open source:
Roblox library

Watch while you eat a pizza completely healthy meal on the couch - YouTube tutorials:
Thorough ProfileService tutorial by @M_nzter
ProfileService in 10 minutes by @CheekySquid
ProfileService tutorial playlist by @okeanskiy
Session-locking explained and savable leaderstats by @EncodedLua
(Will add new tutorials as they come)

A DataStore Profile (Later referred to as just Profile) is a set of data which is meant to be loaded up
only once inside a Roblox server and then written to and read from locally on that server
(With no delays associated with talking with the DataStore every time data changes) whilst being
periodically auto-saved and saved immediately once after the server finishes working with the Profile.

The benefits of using ProfileService for your game’s profiles are:

  • This is my personal module that I intensively support - any bugs you find are also my bugs - In the very unlikely (astronomically unlikely :sunglasses:) case you do find a bug I’ll usually fix it in around 2 - 3 days if you can give me a decent report.

  • Easy to learn, and eventually forget - ProfileService does not give you any data getter or setter functions. It gives you the freedom to write your own data interface.

  • Built for massive scalability - low resource footprint, no excessive type checking. Great for 100+ player servers. ProfileService automatically spreads the DataStore API calls evenly within the auto-save loop timeframe.

  • Already does the things you wouldn’t dare script yourself (but should) - session-locking is essential to keeping your data protected from multiple server editing - this is a potential cause of item loss or item duplication loopholes. ProfileService offers a very comprehensive and short API for handling session-locking yourself or just letting ProfileService do it automatically for you.

  • Future-proof - with features like MetaTags and GlobalUpdates, you will always be able to add new functionality to your profiles without headaches.

  • Made for ambitious projects - ProfileService is a profile object abstraction detached from the Player instance - this allows the developer to create profiles for entities other than players, such as: group-owned houses, savable multiplayer game instances, etc.


ProfileService is part of the Madwork framework
Developed by loleris

Example code:

-- ProfileTemplate table is what empty profiles will default to.
-- Updating the template will not include missing template values
--   in existing player profiles!
local ProfileTemplate = {
    Cash = 0,
    Items = {},
    LogInTimes = 0,
}

----- Loaded Modules -----

local ProfileService = require(game.ServerScriptService.ProfileService)

----- Private Variables -----

local Players = game:GetService("Players")

local ProfileStore = ProfileService.GetProfileStore(
    "PlayerData",
    ProfileTemplate
)

local Profiles = {} -- [player] = profile

----- Private Functions -----

local function GiveCash(profile, amount)
    -- If "Cash" was not defined in the ProfileTemplate at game launch,
    --   you will have to perform the following:
    if profile.Data.Cash == nil then
        profile.Data.Cash = 0
    end
    -- Increment the "Cash" value:
    profile.Data.Cash = profile.Data.Cash + amount
end

local function DoSomethingWithALoadedProfile(player, profile)
    profile.Data.LogInTimes = profile.Data.LogInTimes + 1
    print(player.Name .. " has logged in " .. tostring(profile.Data.LogInTimes)
        .. " time" .. ((profile.Data.LogInTimes > 1) and "s" or ""))
    GiveCash(profile, 100)
    print(player.Name .. " owns " .. tostring(profile.Data.Cash) .. " now!")
end

local function PlayerAdded(player)
    local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId)
    if profile ~= nil then
        profile:AddUserId(player.UserId) -- GDPR compliance
        profile:Reconcile() -- Fill in missing variables from ProfileTemplate (optional)
        profile:ListenToRelease(function()
            Profiles[player] = nil
            -- The profile could've been loaded on another Roblox server:
            player:Kick()
        end)
        if player:IsDescendantOf(Players) == true then
            Profiles[player] = profile
            -- A profile has been successfully loaded:
            DoSomethingWithALoadedProfile(player, profile)
        else
            -- Player left before the profile loaded:
            profile:Release()
        end
    else
        -- The profile couldn't be loaded possibly due to other
        --   Roblox servers trying to load this profile at the same time:
        player:Kick() 
    end
end

----- Initialize -----

-- In case Players have joined the server earlier than this script ran:
for _, player in ipairs(Players:GetPlayers()) do
    task.spawn(PlayerAdded, player)
end

----- Connections -----

Players.PlayerAdded:Connect(PlayerAdded)

Players.PlayerRemoving:Connect(function(player)
    local profile = Profiles[player]
    if profile ~= nil then
        profile:Release()
    end
end)

ProfileService is server-side only - you’ll need replication code to pass Profile.Data to clients. ReplicaService was designed for this job!

1434 Likes
Making Secure and Safe Datastores
Preventing item duplication via trading
Best way to store player properties?
How Reliable are Data Stores?
Data Saving - DataStoreService
Help with Inventory System Concept
Is UpdateAsync() actually better than SetAsync()?
[OPEN] Experienced Scripter/Programmer (ProfileService) [$100USD+ or Robux Equivalent]
CEngine, a nice framework
How would I go about making a fully saving inventory
Stop using SetAsync() to save player data
Help me improve the code for reading and saving data
Best way to make guild system?
Profile Service connect to gui
How do I make a Global leaderboard with ProfileService
Is it worth switching to datastore 2?
[ProfileService] Not properly banning user
Data not being saved
Setup Rojo Fast: The easy way to setup Rojo with Git support
A No-Frills introduction to Session Systems and Efficient Management of Data
I'm having data loss
Multiple Datastores needed?
Datastore not saving
[CLOSED] Zatara | Programmer & Web Developer
[ERROR] ProfileService
Roblox Trading System
Help with Ban table
Tips on how I can change the player's Data?
Update data without overriding data in other servers
How to save a bunch of values in a folder?
Data storing/presenting using ProfileService and ReplicaService!
Feedback on my datastore module
ProfileService cross-game
QuickNetwork - A powerful hybrid alternative to ProfileService and DataStore2
How can I save inventory and save the order of the hotbar / toolbar of a player?
How to make a Strong DataStore
What should I use? DataStore or DataStore2
When should I save data?
Update Log - Build a Private Island (Jan 27)
I need help with quest saving
Help with datastores
The Leaderstats Plugin | EZ Leaderstats! [250+ installs!]
Any Problems With My Data Manager Using Profile Service?
Money wont save
How would I go about making docs for modules?
How do I use Data stores?
How can i make a datastore for this?
How to Script Some Game Essentials
Why is this script not saving data?
Learn to Script / Learn to Code in 5 Steps
How to properly save data with dev products and when
Exploiting Datastorage: REMOTE FUNCTIONS?
DataStore2 data loss on disconnect
How i make a player everytime spawn with a tool after buying it on a shop
How do i make this script more efficient?
What's the issue with my data store?
Help with Ban table
How can I save all descendants of a folder?
Farming World - Information
Is there a way to handle the DataStore corruption error?
Profile Service Data Store
Question about profile service
DataStore Not working
Gamepass Characters with Character Selection Gui
How should I save my table?
Data store not saving
DataStore Queue
Data wont be saved or sent to server after firing remote event using Gui, more info in topic
Help with profileservice
Sword Smith | Script Swords in Just Minutes! [FREE]
Volleyball 4.2 Changelog
When is the best time to save the player's data?
How do I save characters data
How to make a data queue?
In Game Avatar Editor v2
Saving items to an inventory
Project Delta Credits
How to make a game like this?
Good method for data storing tables / dictionaries?
Data is being erased
Farming World - 3.0
Datastore won't Save
Issue with ProfileService dev products handling
Give player sword if time is whats expected
PSManager (CURRENTLY NOT UPDATED) - Automating ProfileService + know when your Profile.Data has been changed!
Help with DataStore (SOLVED)
ProfileService - ProfileTemplate not set
Fixing and cleaning up large if/then walls
How can i save pets?
I'm so fed up with data loss, please help!
Detecting if a key's value is changed in a table
How should I use & access save information using ProfileService?
Help nudge me in the right direction
Session Locking (I'm stuck)
The Best Way To Save Player Data
How should I use & access save information using ProfileService?
Few Questions on dataStore
DataStore request was added to queue. If request queue fills, further requests will be dropped. Try sending fewer requests.Data Store
Data Stores 2 saving / loading issue
Multiple Players Save
Is there an advanced dataStore that does not have data loss?
Is there a max Datastore can save?
How can i make a saving inventory?
DataStore Question
Don't understand the _G
Arcade Island Credits
BigLeaderstat - Bigger leaderstat system that goes past the 9.2 quintillion limit
Why is my player data table nil when it should be printing the data?
99% Fail - Updates and Credit
Volleyball 4.2 Useful Info
Problem with Data Stores
How do I make a datastore that saves a leaderstat?
How would I save a certain part of the game?
Internal Services Are Down; Players Are Already Losing Data & Robux
DataStore request was added to queue. If request queue fills, further requests will be dropped. Try sending fewer requests.Key = Player_1234
Help with DataStore (read for info)
What's the best way to handle a bunch of datastore requests?
Roblox Data Store v2 or Kampfkarren Data Store 2?
Dataloss issue/datastore2 advice needed!
Roblox Data Store v2 or Kampfkarren Data Store 2?
Part Counter GUI Help, How do i make it? (Egg Hunt)
How to use DataStore2 - Data Store caching and data loss prevention
Should I release the game with roblox data store?
How do popular games do leaderboards, or datastores in general?
How to prevent data loss if I want to save every time coins save
Player Count (Ask)
Current Best Practices / Libraries for Data Storage?
"Wanderers" Update Board
For some reason datastore saves only one data
I don't understand the datastore limit
Datastores vs Datastore2
Script not updating player's data
Player Experiencing Data Loss in my TD Game
How do I check if the data of the player is empty / if it's his first time playing the game?
Saving "Time Played" Leaderstats
How do you store data properly?
How can I keep my data from saving if pcall fails?
How would I go on making an Update Log alike the one in PSX or Clicker Simulator?
DataStore request was added to queue (lost all tool data)
Datastores screwing me over (No error message?)
How to compress huge tables? (more than 1M characters)
Points System Issue
Is it better to have multiple DataStores?
Cannot store data to DataStoreService
MongoStore - An alternative to DataStores
DataStore request was added to queue (lost all tool data)
Datastore broken
Datastore broken
More efficient server-client data model?
Stop using SetAsync() to save player data
Monsters of Etheria Attributions
Very simple error I can't solve
How to find largest DataStore2 value
About Rainy Vibes
How can i improve this DataSave script?
Datastore overview + advice and/or critisism
Datastore giving player another players money
Tables are not saving
Is there a way to easily make a datastore that includes a lot of values?
Datastore completely wiped
Replicated storage - what modules should be included their?
Datastore keep resetting
Session locking explained (Datastore)
DataStore not working
DataStore2 does not work properly when using TeleportService
Attempt to index nil with 'leaderstats'
Roblox: Survivor | Credits
How do I make a secure trading system?
Replicated storage - what modules should be included their?
Data not saving for players
Is there any way to communicate in between places of a game?
This doesnt work for some reason
Can you change a profile service value multiple times?
Data Rollback / Reverted
Transfering Data between games without teleporting
Why won't just 2 stats save?
Outside | Credits
Is this a bad practice?
Issue with DataStore for a Shop / Loadout
Would it be a good idea to save data values in different datastores? (explained in message)
Data loss (DataStore)
How can I save tables to datastore
DataStores questions
Lunar Data Module
Which is better, ProfileService or DataStoreService? and How ProfileService works
Problem With Saving Data
How could this datastore code be improved?
Terrain Saving/Loading
How could i make a sort of purchase saving system?
Leaderstat Making
Should I switch datastores?
Dictionary Inventory for every player
[V1.1] Leaderstats Plus - Leaderstats have become unimaginably easier
ProfileService Tutorial!
Help with Mail System
How would I Prevent Data Loss when Player Leaves using DataStoreService?
How to stack backpack items (Unsolved)
What is the best way to save Player Data?
How to make a saved global variable?
General datastore issues, further info in post
I feel like this script was too easy to script
DataStore: SetAsync() vs. UpdateAsync()
Datastore help needed!
Datastore and the headache that comes with it
No Title Game - Credits
Datastore sends errors DataStore request was added to queue. If request queue fills, further requests will be dropped. Try sending fewer requests
Replicate your states with ReplicaService! (Networking system)
The best way to save data is?
Script not detecting folder
Should I be using UpdateAsync, SetAsync, or ProfileService?
Help Needed with Game Table Data Store in Roblox
Saving folders content with Datastore2
What is DataStore? Also how to implement it in my games?
DataStore saving data help
Help With Leaderboard
Messaging between experiences
How could I make a player market?
How to make equivalent of Instance:GetFullName for tables
CreativeOS | The first available OS API
What is the best way to store player data?
Custom inventory data storage
How would i datastore save if i possess an certain Spell?
[Guide] - How to make a Global leaderboard with ProfileService?
How often should I save data?
Saving multiple tables
Player removing firing with BindToClose
What are some good times to do a datasave on a obby
Easy to Use player stat module
Magic Fighting Simulator - Information
Item Stacking Problem
Saving Tools Datastore
My datastore is not working
Help with datastore
How to store "special" UTF-8 characters with datastore
Data Stores - Need help with understanding
How to make a data backup for a tycoon
How do i make tools save across places?
Inventory Datastore Help
How to save data table in game in right way
Datastores not working correctly
How do i share data from server 1 to server 2 i would be really grateful if someone tells me
How to delay SetAsync calls to avoid sending too many requests?
How would I make my own inventory system?
Data not always saving on PlayerLeaving
DataStores not saving and loading properly
UpdateAsync is returning old values from months ago
Roblox Lua Programming Formalities Guide
Saving Progress With NPC In Data
SmartData - Save your data without coding
How can I access ProfileService from two different scripts?
Studio crashes if opens large scripts quickly
Product: exe | Most Stunning Admin Panel Yet
SmartData - Save your data without coding
Best way to preserve data
Game Suddenly Not Functioning Properly
A better way to store data?
Error while loading datastore? [SOLVED]
Data loss issues with datastores
Save Server Data With profile service
Giving A player their own Prison cell
DataStore SetAsync not working
Best/Easiest way to save player data
Easy Datastore - new and easy datastore module
Best/Easiest way to save player data
Save Data Problem
Feedback on my very first datastore script
What's best for data receiving/saving? Loops, or the "standard" method?
[pls help] Best way to save data/values from folders using DataStore2?
Datastore best practices
How to wait until ProfileService finishes loading?
DataStores, if SetAsync or UpdateAsync gets called, but is not finished with writing yet, what will GetAsync do?
Allow players to save and load settings using DataStore
Better way to send Money
How to organize a character save slot system?
Datastore wiping if I leave and rejoin too quickly
Need help with Storing DataStore in my Sol's RNG-like roblox experience (it does not save rn)
Help with data loss
Need help with Storing DataStore in my Sol’s RNG-like roblox experience (attempted ProfileService)
Plot Saving System
How to let players save OC's with a custom character?
ProfileSync - A Simple ProfileService Wrapper and Replicator
Obby with difficulties Data Saving
Getting the name of a player from data store
Sending Data to Client (Profile Service)
DataStore with Session Lock
How can I find how long it's been since a player plays my game last?
Datastore not working
Data Stores Observability Dashboard
Most preferred / Best Frameworks?
Help saving folders, and the instances inside
Datastore not working
Boston Remastered: Credit List
How would I save if a player bought something?
Minute Counter Bug!
DataStore not working
A question about saving huge amount of data through the datastore
Is my script secured enough?
Best place to store player stats while being accessible by the player?
Which datastore method should I be using?
Changing Data without resetting the data
Would like feedback on my datastore and developer product purchase code!
How to make Data Store script more secure?
How to use DataStore2 - Data Store caching and data loss prevention
How can I save progress?
99% Fail Impossible Obby - Credit
Issue loading player data with ProfileService
My game has data loss and I dont know how to fix it
Data won't save if player leaves before like 20 seconds
Data Store Error
Strange issue prevents data from saving in all places unless someone else joins Team Create
Tips on saving large amounts of data
Help Needed for Backing Up Player Data in ProfileService
DataStore isn't saving Players points
How should I work within the 6-second DataStore write limit?
Roblox Scripting Roadmap & Learning Resource List
Using DataStore2 for multiple saves
Better Chat V3 | Feature-rich custom chat with replies, rich text, message editing, and more!
DS2Handler - An easier, simpler way to use DS2 (Open Source)
How does ProfileService have session locking?
PlayerAdded Not firing?!
Superblox Racing - Information & Credits
How are skill slots possible?
LocalScript FireServer not firing when player leaves the game
So You Wanna Script: A Reference Guide for Everyone Else
Open Sourced Inventory System
How to make DataStores?
Duping On Cross Platform Games
Data Store Issues
Recent Datastore Issues
Is there any issues with this datastore?
DataStore Question
Are there any improvements I should make to this data store
Fixing a shop saving problem
DataStore2 Stuck?
DataStore Question
How to use DataStore2 - Data Store caching and data loss prevention
Error: attempt to perform arithmetic (sub) on number and nil on ProfileService DataStore
Saving Script seems to be working inefficiently
How Can I Improve This Pet Saving System?
How to save data with profile service
How to use DataStore2 - Data Store caching and data loss prevention

This sounds extremely useful, as I find it difficult sometimes to create reliable datastores/properly handle saving and loading player data.

I assume from reading the post that this module handles errors when loading/saving data?

53 Likes

It silently handles all errors while maintaining expected behavior of all its methods and it sends the errors to the endpoints (like ProfileService.IssueSignal) if you wish to set up analytics. Errors will also appear as warnings in the developer log by default.

57 Likes

Really like how efficient this module is. The Global Update element is extremely useful. Especially given it has no additional expense as far a date store calls go. The ease of use and error handling further boost the Mad greatness (pun intended) of the Profile Service. Will definitely be making use of it in a future project.

26 Likes

Came in clutch with this module loleris, I was just looking for a datastore module to use for my game. Thanks.

23 Likes

This is so nicely written and absolutely useful! Legend!

18 Likes

This is a really efficient module, I don’t think people realise that abusing datastores doesn’t make a better datastore. They kind of go with the “if it works it works” attitudes of things.

Thanks for making every compulsive perfectionist’s dream come true.

24 Likes

This is definitely great for newer developers!

However, would there be an advantage to using this over a standard data-storage handler?

In addition, does this provide competition to DataStore2, which is already used by many?

20 Likes

On the contrary, it’s a module well suited for beginners while pretty powerful for advanced scripters - ProfileService is disconnected from Player join / leave events and offers no :Get() or :Set() methods for the profile data - all of this is left to be managed by the developer according to their personal preferences. ProfileService API is short and to the point - it does nothing but handle profiles and it does it perfectly.

Also this module is based on the DataStore implementation I’ve been using in The Mad Murderer 2 where data loss AND item duping were never reported except the time when Roblox did a big oopsie.

39 Likes

Awesome! I’ll have to try it soon for newer projects, I’ll have to come back with results soon :slight_smile:

12 Likes

Amazing job on this! The use of a single DataStore API endpoint had me baffled for a minute, but after looking through it I found your solution to session locking ingenious. This seems like a completely superior data management solution to any others that I’ve seen and I have no doubt in its ability to gain traction.

20 Likes

Will ProfileService automatically release if the server crashes without calling BindToClose? You could possibly abuse MessagingService to check if a server is still alive.

8 Likes

If the server crashes the Profile will indeed become session locked by a dead session… Actually I decided to opt-out not_released_handler = “StealSession” functionality which would let the developer instantly steal the session lock for a profile, because it would not be a 100% safe way to handle data. Basically, the dead session locked profile problem solves itself when the developer is using ProfileService as they regularly would:

After passing not_released_handler = “ForceLoad” (or return "ForceLoad" via function) the player would be forced to wait for the game to load for little over a minute. ProfileStore would fail to make the dead session release the profile and would “steal” the session lock after a built-in timeout (which is, again, about 80’ish seconds). Try to make the player enjoy the passage of time via an animation that would simulate progress, some sort of entertaining animation or even a small minigame.

If, however, your game has profiles that may persist after a player leaves, then you would first try to teleport the player to the JobId returned by the not_released_handler (“Cancel” the profile load request to finish the ProfileStore:LoadProfileAsync() call and use TeleportToPlaceInstance. If the teleport fails, call ProfileStore:LoadProfileAsync() again with “ForceLoad” on this session. Obviously in such system you would need to check if a profile is loaded inside the server for that player, because calling ProfileStore:LoadProfileAsync() again before releasing the same profile will cause an error.

If you wish to create your own custom logic of asking a LIVE remote session to release the profile, then the return "Repeat" callback for not_released_handler can be handy - Passing “Repeat” waits for 15 seconds and retries session locking the profile. If the profile has not been released, not_released_handler is called again.

27 Likes

This is awesome @loleris, thanks for sharing us your resources

- can you add a source file for using with rojo on Github? nvm

  • does it use MessageService internally as well?
10 Likes

ProfileService can be applied within your Rojo workflow as any regular ModuleScript you would create for your game yourself.

ProfileService only relies on :UpdateAsync() to power all of its features - it will not know whether the Roblox server that has the profile currently locked is actually alive or dead. However, in practice we don’t need to know that as most Roblox servers will not be crashing everyday and the only downside to Roblox servers crashing one day is that your profile requests will be handled in a minute instead of 1-2 seconds.

15 Likes

.OnUpdate doesn’t work how does this module address that?

  • so I was wondering how the code detects changes across servers?

I know that the code is compatible, I meant set up like this for Rojo GitHub - Sleitnick/AeroGameFramework: AeroGameFramework is a Roblox game framework that makes development easy and fun. The framework is designed to simplify the communication between modules and seamlessly bridge the gap between the server and client. see src Folder nvm I thought it wasn’t a standalone module like most, sorry my bad

I haven’t got to read the source yet

8 Likes

Instead of subscribing to changes it scans for changes periodically every auto-save which happens every 30 seconds for every active Profile.

10 Likes

A wiki page with a completely barebones “getting started” example could be very useful for beginner scripters - one of the reasons some prefer DS2. For example, omitting the player:IsDescendantOf if statement for the sake of simplicity. Also I might have misread the example, but there doesn’t seem to be a use for Workspace.

A quick example using how global updates might interest people too.

13 Likes

I might use this as a secondary backup

10 Likes

In my opinion, this module should be used as your primary data management solution with bereza’s method of saving data as backups, if you really want them. This module seems to handle lots of nasty edge cases you ordinarily would just have to encounter yourself before you figure out how painstakingly difficult they are to fix.

5 Likes