How does scope in DataStores work?

Okay, I’m still a bit confused of how scope in DataStores work. As I go through the Roblox documentation, there’s a lack of explanation about it.

If you could illustrate how the hierarchy of a DataStore, how would it look like?

Maybe like this…?

DataStoreService
  Data Store Name
   Data Store Scope (optional)
    Data Store Key & Its Value

Any information/opinion about it will be helpful, thanks!

17 Likes

To be fairly honest, I dont think it’s often used this scope field.

Though I do think that your idea of scope is correct.

1 Like

I think it all boils down to personal preference, there’s nothing special about scopes in general from what I can tell. I do use them though, to keep things relatively clean.

For example:

::GetDataStore("GameUserData", player.UserId):GetAsync("Data");
::GetDataStore("GameUserData", player.UserId):GetAsync("LocalSettings");

Versus

::GetDataStore("GameUserData"):GetAsync(player.UserId).Data;
::GetDataStore("GameUserData"):GetAsync(player.UserId).LocalSettings;

EDIT
& in terms of hierarchy, it’d say it’s more so:

> DataStoreService
	> Name | Scope [<default> Global / <custom> Named]
	> Data

I can’t speak on how gracefully it’d scale with growth because I haven’t gotten to that point (although I can’t think of any reasons why it should be a problem), but here’s an excerpt on how I have it implemented:

local DatabaseKey = "GameUserData";

function Database:fetch(player)
	local UUID = tostring(player.UserId)
	
	local UserData = DataStore:GetDataStore(DatabaseKey, UUID) 

	if UserData then
		for attempt = 1, MaxGetAttempts do
			if attempt > 1 then
				warn(string.format("DataStore GET attempt [%d/%d]"), attempt, MaxGetAttempts);
			end
			
			local success, response = pcall(function()
				return UserData.GetAsync(UserData, "Profile")
			end)
			...

5 Likes

Yes, but in a hierarchical manner of the objects inside DataStoreService, where do you think scope would be located?

From your quote, I could say that scope acts like a sub-datastore where you can store your keys and its values in it?

Well then, is it possible to use scope to store more data, perhaps something like this?

GetDataStore("GameUserData", LocalSettings):GetAsync(player.UserId).SettingA
GetDataStore("GameUserData", LocalSettings):GetAsync(player.UserId).SettingB
GetDataStore("GameUserData", Data):GetAsync(player.UserId).NormalData
GetDataStore("GameUserData", Data):GetAsync(player.UserId).ExtraData
2 Likes

Oh yeah for sure, GetDataStore("GameUserData") uses the global scope, so the only difference with GetDataStore("GameUserData", "Scope") is that you’re using a new named scope as opposed to the default one.

::GetDataStore("GameUserData", "Data"):GetAsync(player.UserId).NormalData

^ …is valid

3 Likes

This is the whole database system:


(The scope is optional)

16 Likes

Scopes are just used to partition data into other sections. Think of them like subfolders in a DataStore. When you don’t specify a scope, your DataStore actually still uses a scope - the default scope, which is “global”. Specifying a scope puts a DataStore at the same level as one without it.

DataStoreService
 DataStoreName
  DataStoreKey
 DataStoreName Scope_global
  DataStoreKey
 DataStoreName Scope_safe1
  DataStoreKey

Think of it like your computer’s file system.

When you get a DataStore, you open up the main folder which is the first string you specify to GetDataStore. When you don’t specify a scope, it defaults to global and opens the global subfolder. If you specify a scope, it creates and opens the new folder which is the scope you set.

43 Likes

I don’t think there is an real hierarchy for datastores, scopes are basically just another way to distinguish datastores similar to data store names.

Whenever you get a datastore with a new data store name and scope it adds an instance under DataStoreService, could this mean a memory leak if you get a unique datastore for each player?