Easy Datastore V2 | The easiest DataStore on Roblox

Easy datastore is indeed on par with Datastore2 and ProfileService as it implements many best practices like caching, session locking, etc.

Also you should be wary or making bold, subjective, and ignorant claims such as it “not adding to the datastore scoop.” Easy datastore is a easy to settup, easy, clear, and consise module to code with, and should be considered a serious competitor.

I appreciate your mention that we should consider new modules and I agree. What I want to emphasize with the rest of your feedback though is that it is balant insults and not constructive critism as you are claiming negative aspects of my module without actually proving this.

Its not fair to me as the developer for you to say that my module does not “live up to its apparent better competition” when you have no proof or teating on the module and likely barely used it.

1 Like

Another thing that I would like to mention with ProfileService:

ProfileService is not meant to be super easy to use stand-alone. “It gives you the freedom to write your own data interface”. The idea is that you can use it to create your own system for data saving. The module only manages saving and accessing profiles.

DataStore2 is explained as a “wrapper module”, mostly saving “duplicates of your data”. The big win with ProfileService over DataStore2 is it is able protect against “item duplication exploits” because it is an “extension module”.


All this to say, EasyDatastore is great for smaller games, newer developers, or inexperienced programmers as it manages everything for you. Because the module creates it’s own system for managing data using player attributes, you can easily get attribute changes on the client without any prior setup, as the module updates the attributes every time a value is changed.

Being able to do Module:set() and Module:get() is very similar to how DataStore2 works, where you have setter and getter functions, however, everything is pre-configured, proving EasyDatastore “easier” than setting up DataStore2.


There are still tests to be done with the module, however.

The way that the module works:

  • Does it work similarly to ProfileService or DataStore2 when saving and loading data?

  • Is the client able to change values in the data table?

“Battle testing”:

  • Does the module protect against item duplication exploits?

  • Does the module protect against spam setting/getting (true session-locking)?

  • Does the module protect against failures with getting data (retry functions)?

  • Etc.


There is still lots to be tested against and answered before we can call this module “complete”, however, as it stands right now, it seems to work really well!

I’m pleased to answer any EasyDatastore-related queries, and I appreciate your skepticism.

Limitations: I created EasyDatastore because I considered Datastore2 and ProfileService to be overly challenging due to their departure from conventional modular standards, which has resulted in knowledge gaps about how they now operate.

Simplicity: Simplicity in game development speeds up the process and creates mental space for more new ideas. It promotes teamwork, improves script clarity, and facilitates debugging. However, leaning too heavily on simplicity might result in complacency and overlooking. This raises the question: Does increasing complexity result in more control? While profile services and datastores provide developers with more “control” over the data structures, EasyDatastore retains configurations that can be readily altered within the script as well as direct code manipulation.

Audience: EasyDatastore’s accessibility is not restricted to new developers or small games. Its simplicity and dependability make it suitable for projects of all sizes. EasyDatastore can handle all data types provided by ProfileService and Datastore2, making it ideal for large-scale games. Its easy architecture encourages collaboration among several developers, making it ideal for larger projects with complicated requirements.

Workings: EasyDatastore acts similarly to ProfileService and Datastore, however it is a standalone solution. While it serves the same purpose as data storage services and addresses common concerns such as data corruption and server crashes, it is a unique module. EasyDatastore is reliable and designed for developers of all sizes, having been built on proven best practices and developed through feedback. With the release of EasyDatastore V1, useful insights were obtained, resulting in enhancements such as autosaving and session locking, which improved functionality and usability.

Security: EasyDatastore limits client access to only reading data via the get method, which ensures security. The server still has the power to alter values and access set functions. This setup ensures data integrity and prevents unauthorized changes. Furthermore, session locking reduces item duplication by controlling access to resources during data operations.

Reliability: EasyDatastore protects data through multiple mechanisms:

  • Anti-corruption: Using updateAsync, EasyDatastore ensures that new data does not overwrite existing data, preventing data corruption.

  • Session locking: It inhibits the creation of new sessions while old ones are active, ensuring data integrity throughout transactions.

  • Data recovery during run-time: EasyDatastore uses autosaves to restore the most recent data whenever corruption is discovered, ensuring ongoing functioning.

  • Error handling EasyDatastore handles problems by making several tries to get data. It defaults to retry data retrieval five times, but you can change this in the data script.

  • Meaningful saves: EasyDatastore saves data only when changes are made, avoiding resource utilization and wasteful write operations.


In conclusion, despite the potential limitations of simplicity, EasyDatastore strikes a balance by offering options and allowing direct code changes. Its adaptable data template accepts any data types (excluding objects), which increases flexibility. EasyDatastore’s simplicity promotes clarity and collaboration in programming, making it useful for games of all sizes, from large-scale productions to smaller indie ventures. Overall, EasyDatastore is a wonderful asset for game creation across the board.


Sources:

  • ChatGPT-inspired writing format
  • Grammarly & Quillbot grammar checker
  • Quillbot paraphrase
1 Like

I would agree that the accessibility isn’t limited, I would argue that the use case is limited (slightly). As explained above, it’s pre-configured. All I am saying is that most larger games will likely want to develop their own system of managing data, as it is private, custom, and modifiable. This is not to say that EasyDatastore can’t be used in large production games, it’s just stating the fact that larger game developers may want to rely on a custom data management system with DataStore solutions like ProfileService, letting them manage data however they wish.

Could you link this post? I would like to test the differences of each version, if possible.

This is true, however, I find the Module:get() function on the client useless. Not because it wouldn’t be useful, but because it requires you to store the module in the workspace and because the module automatically creates and updates attributes inside of the player, which the client can access instead of the module. This would also improve security, as the client is unable to access the module at all in this case.

Essentially, in my opinion, I would get rid of client compatibility of the module. The only thing the client should ever need from the module is the player’s data, which is replicated and stored in the player’s attributes anyway. The client can just update client values based on updates to the attribute.

Not entirely sure why you included this lol.

I used the format chatgpt uses as I presume it is based on a significant amount of training data. For example chatgpt uses data from users to improve its capabilities.

I noticed that chatgpt started listing the number of paragraphs above each paragraph so now Im doing that too.

1 Like

This is the old post

I greatly improved the formatting based on criticism in the original post, so I assumed it would be fine to apply this input to EasyDatastore V2 as well.

1 Like

you can make something better in like 20 minutes
hell, i made something better in 10 minutes

this is useless

1 Like

Looking at the library for this, I don’t think its better.

While this is EasyDatastores:

You also stated that “you can make something better in like 20 minutes.” Thank you for your comments; could you please mention some of the capabilities that you believe are missing or should be improved? This feedback allows the module to evolve and improve as I respect your knowledge and insights in the field of data saving.

1 Like

Didn’t this guy like make 2 really bad community resources and have a very bad past?

but hey if this one is good then maybe this is the comeback of the century?

6 Likes

Thanks for the feedback, I’m glad you find this post a good resource :smile:

1 Like

Okay, a couple changes I would like to propose.

Client Folder:

Just remove it. There is no point in having a Module.get() function on the client. It would be way easier to just do this, as the module already updates the player attributes:

player:GetAttributeChangedSignal(attributeName):Connect(function()
    local value = player:GetAttribute(attributeName)
end)

Noob Compressor?

First of all, what a terrible name. Second, what does it even do? I get that it “compresses data”, but for what purpose? After editing the “EasyDatastore” module and removing the “noobCompressor” module, everything still works fine.

Seperate Autosave Script:

Why not just combine the autosave feature into the module? Also, I would recommend you use a RunService.Heartbeat function instead of while true do. This is more efficient and allows for other tasks to be ran in the module.

This leaves me with my last proposal:

Module Name:

Because it looks better, I would recommend changing the name to “EasyDatastore” or “EasyDatastore2”, with a capital E.


All of the above changes leave you with a standalone module. No children in sight!

I have gone ahead and made all of these changes myself.

  • I commented out any mentions of “noobCompressor” and adjusted the function to use the default data instead of the encoded/decoded/compressed data (I am not really sure what it did lol).

  • I removed any mention of the “get” event and altered the script to run on the server.

  • Combined the “autosave” script with the module at the bottom, changing the while true do loop to a RunService.Heartbeat function and calling any necesary functions. I then changed the module functions that deal with autosaving data to regular script functions, which will clean up the user experience when calling events with the module. I also adjusted the way that the the autosave function works. Before, the “autosave” script would only save a single player’s data every minute. This means that it would take 10 minutes to autosave everyone’s data once if there were 10 people in the game. I instead changed the function to loop through every player in the game and save everyone’s data every minute (or whatever the save frequency is set to).

  • Finally, I adjusted the name to have a capital E and placed it in ServerScriptService, as it is far more secure there.


EDIT: Another thing I noticed with the documentation:

You shouldn’t require the module EVERY TIME a new player joins. You should instead require it once on the server and then manage it from there.

local EasyDatastore = require(ServerScriptService.EasyDatastore2)

Players.PlayerAdded:Connect(function(player)
    local coins = EasyDatastore.set(player, "Coins", 10)
    print(coins) -- 10
end)

EDIT-EDIT: Yet another thing:

The Module.subtract() function does not check to ensure that the value will not result in a negative number.

What I would do is create a bool parameter in the Module.subtract() function called “canBeNegative” or something similar. If this is true, then don’t check if the value will result in a negative value, however, if it is false, check to make sure that the final updated value is not going to be negative.

function checkNegative(plr: Player, currencyName: string, amount: number): boolean
	local currency = serverPlayersData[plr.UserId][currencyName]
	if currency - amount < 0 then
		return false
	else
		return true
	end
end

function EasyDatastore.subtract(plr: Player, currencyName: string, amount: number, canBeNegative: boolean): number
	local currency = EasyDatastore.get(plr, currencyName)
	checkIsNum(currency, "subtract()", "currencyName")
	checkIsNum(amount, "subtract()", "amount")
	local negative = checkNegative(plr, currencyName, amount)
	if canBeNegative or not negative then
		return EasyDatastore.set(plr, currencyName, currency-amount)
	else
		return EasyDatastore.get(plr, currencyName)
	end
end

EDIT-EDIT-EDIT: Types…

I noticed that with all of your functions you are not including types next to the parameters.

Doing this:

function Function(value: number, value2: string, value3: boolean): number

As opposed to this:

function Function(value, value2, value3)

Makes it a lot easier to understand what parameters to give functions, especially module functions.

Right now this is what the module shows when I call a function and pass in parameters:

image

If we add types to these parameters it suddenly becomes a lot more clear what should be passed in:

image


Here is the module with my applied edits:

EasyDatastore2.lua (13.3 KB)

Modules only run the code inside when its required. I want the autosave to run constantly even if its never required. For this reason I put it inside of a seperate script.

Noob compressor compressed the data to free up space in the datastores

Sure ill remove module.get()

Sure ill change the name

Sure ill change it

Sure ill change this

Some people might not want it to stop at 0.

Sure ill change this

2 Likes

It’s much safer using Profileservice with an easy wrapper on top of it than using this datastore at the current state. Especially for the “smart” features that completely lacks compared to Profileservice and datastore2, especially regarding safety of the data and session locking. If possible, please revise them to ensure effective safety for the people who use this in their game.

Thank you for the feedback on easydatastore. I hear you mention that EasyDatastore lacks in the fields of autosaving, session locking, and data security. If you could specify in which ways I can improve the current version, that would be most helpful. To clarify, how it currently works:

autosaving: Every 60 seconds, at spaced intervals (determined by currentPlayers/60), autosave the data if the user has made changes since the last autosave.

session locking: When a user joims the game, check if a session is already active. If it is, kick the player and delete the session. If its not, create a new session. When the user leaves the game delete the session with the final save.

data security.: The client can only access module.get(), but cannot affect any of the data. module.get() is needed to pass larger peices of data such as entire tables and dictionaires to the client. All module.get() does is ping a remote function for the server sided version of the module.


To my current understanding, these practices have been implemented effectively. If you have any feedback on how to improve them speficially, or the differing ways in which other modules manage these funcitonalities, I’d love to hear!

1 Like

Do you still work on Furry Detector 2.0? If so, I think this would be a great fit to streamline your data storage paradigm.

Jokes aside, I’d recommend anyone reading check out other data modules. Dealing with player data can be finnicky and have serious consequences if mishandled. This isn’t an issue about this module being worse than the rest, but rather that when dealing with data storage you need to be confident that the code you’re relying on is robust and thoroughly tested. Considering how a significant portion of the 45 replies in this thread are about code malpractices and false claims made about the quality of this module, I think it’s worth looking into other options.

Aside from the popularly known DataStore2 by Kampfkarren and ProfileService by loleris, there are many options for DataStoreService wrappers that may give you more confidence that your data is being handled properly. One I’ve had my eye on recently is lapis by nezuo but I’d also strongly recommend looking through both the guide and related example code for the datastore wrapper you can find on the Roblox documentation.

If you’d like to seek out other modules aside from the ones I’ve listed, I recommend using the search terms “DataStore Wrapper” and “DataStore Module” here on the devforum to find a wide variety of different (and less controversial) data solutions.

1 Like

I understand that it can be difficult to have confidence in new modules, but if you ignore EasyDatastore for that alone, you may be missing out!

@GRIMNO1RE I understand the serious nature of data management, and I also understand that confidence is key in such situations. I want to assert, however, that you should give EasyDatastore an opportunity. It has numerous valuable benefits for datastore collection.

Alternative modules such as Datastore2 and ProfileService are indeed excellent modules; however, there are also some considerations. EasyDatastore has the benefit of simplicity, which allows cleaner and more efficient code. Furthermore, the learning curve of both Datastore2 and ProfileService is generally higher. While there is the added benefit of more control over data, EasyDatastore is still designed to be highly scalable and reliable, competing with these known modules.

Despite its “easy” nature, EasyDatastore can be an excellent addition to complex, small, and even big games. In bigger games, teams can collaborate more effectively with a simpler data store library. It frees up space for bigger ideas and makes even those knowledgeable about datastores understand the functionality. Furthermore, the abstracted nature practically eliminates developer error. In modules like ProfileService that require lots of manual configuration, even small mistakes can make big differences in data integrity.

As you mentioned,

This can cause frustration and confusion among developers using more complex solutions. Furthermore, simplicity can speed development, clear up code, and make collaboration easier. For these reasons, I strongly believe EasyDatastore can be a valuable addition to the market.

As for my expertise, I have analyzed and learned about numerous best practices. I have implemented a variety of elements to ensure that data is managed reliably and that you can be confident in using EasyDatastore. However, like all things, there may still be mistakes. But this doesn’t mean we should completely abandon EasyDatastore. And with the acknowledgment of these mistakes, I still want to emphasize that EasyDatastore has been heavily tested.

EasyDatastore has undergone various forms of testing and is quite reliable. While the replies in the post can give the sense that there are constant issues, this is simply not true. Many of these replies are suggestions to further improve clarity for new developers and optimize the functionality. However, it’s important to acknowledge that this is a natural part of the growth of new modules.

So I encourage you to embrace EasyDatastore. Everything must start somewhere. Give it a chance! I’m excited to see where this project goes, and I hope you do too!

How do I access the table in my template and add a string to it?

You can access a table in the template with


  1. Module.Get(plr, “Name”)

Plr: The player model located in game.Players
“Name”: The name of your table


You can add a string to the table with

  1. Module.Set(plr, “Name”, String)

String: Whatever string value you want to change it to.

that doenst work either I tried that and it says argument #1 expects a string, but table was passed