You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description: When to use standard data stores, ordered data stores, and memory stores.
4
+
---
5
+
6
+
To store data, you can use [data stores](./data-stores/index.md) with the `Class.DataStoreService` or [memory stores](./memory-stores/index.md) with the `Class.MemoryStoreService`.
7
+
8
+
Alternatively, you can also use Lua types and variables to [store data in-memory in Lua](#when-to-use-in-memory-storage-in-lua), without using the data or memory store services.
9
+
10
+
## When to Use Data Stores
11
+
12
+
The `Class.DataStoreService` stores long-term data that needs to last between sessions, such as user progress or inventory items. Data stores are consistent per experience, so every server for every place within an experience can access and change the same data. There are two types of data stores: standard and ordered.
13
+
14
+
**Standard data stores** can store data like numbers, strings, and tables that don't need to be ranked or sorted. This data is stored as key-value pairs, where each entry is stored under a key that is unique within its data store and that you can retrieve, update, or delete.
15
+
16
+
**Ordered data stores** can only store numbers. Each entry is stored under a key that is unique within its data store and that you can retrieve, update, or delete. You can rank and sort this data numerically and retrieve it in ascending or descending order based on stored numerical values. For more information, see [Ordered Data Stores](./data-stores/index.md#ordered-data-stores).
17
+
18
+
<table>
19
+
<thead>
20
+
<tdwidth="10%"></td>
21
+
<tdwidth="30%">**Standard data stores**</td>
22
+
<tdwidth="30%">**Ordered data stores**</td>
23
+
</thead>
24
+
<tbody>
25
+
<tr>
26
+
<td>**Data type**</td>
27
+
<td>Numbers, strings, booleans, and tables.</td>
28
+
<td>Only numbers.</td>
29
+
</tr>
30
+
<tr>
31
+
<td>**Common use cases**</td>
32
+
<td>User progress, inventory items, and experience settings.</td>
33
+
<td>All-time, persistent ranking systems and leaderboards. Unlike leaderboards in memory stores, this leaderboard data is permanent.</td>
34
+
</tr>
35
+
<tr>
36
+
<td>**Past version backup**</td>
37
+
<td>Automatically manages previous versions of your data for 30 days.</td>
38
+
<td>Does not manage previous versions of your data.</td>
39
+
</tr>
40
+
</tbody>
41
+
</table>
42
+
43
+
<Alertseverity="info">
44
+
Data stores can only be accessed by server-side scripts.
45
+
</Alert>
46
+
47
+
<Alertseverity="info">
48
+
If you want to add granular permission control to your data stores and access them outside of Studio or Roblox servers, you can use [Open Cloud APIs for data stores](/cloud/reference/DataStore).
49
+
</Alert>
50
+
51
+
## When to Use Memory Stores
52
+
53
+
The `Class.MemoryStoreService` is a high throughput and low latency service that stores temporary data that needs to be updated or accessed frequently, such as global leaderboards or matchmaking queues. With memory stores, every server for every place within an experience can access and change the same data quickly and frequently. Data in a memory store expires after a certain period of time, lasting up to 45 days.
54
+
55
+
Although memory stores store temporary data, they also support permanent features like a global marketplace. The marketplace is permanent, but the items for sale inside it have an expiration date.
56
+
57
+
<table>
58
+
<thead>
59
+
<tdwidth="15%"></td>
60
+
<tdwidth="50%">**Memory stores**</td>
61
+
</thead>
62
+
<tbody>
63
+
<tr>
64
+
<td>**Data type**</td>
65
+
<td>Numbers, strings, booleans, and tables that don't need to persist for over 45 days.</td>
66
+
</tr>
67
+
<tr>
68
+
<td>**Common use cases**</td>
69
+
<td>Skill-based matchmaking, match states for multiplayer games, daily and monthly leaderboards.</td>
70
+
</tr>
71
+
</tbody>
72
+
</table>
73
+
74
+
## When to Use In-Memory Storage in Lua
75
+
76
+
You can use in-memory storage in Lua to store temporary data that needs to be accessed with minimal latency and without the cost of making external service calls to data stores or memory stores. There are no extra steps required to set up in-memory storage as it's already built in by default in Lua.
77
+
78
+
<table>
79
+
<thead>
80
+
<tdwidth="15%"></td>
81
+
<tdwidth="30%">**In-memory storage in Lua**</td>
82
+
<tdwidth="30%"></td>
83
+
</thead>
84
+
<tbody>
85
+
<tr>
86
+
<td>**Data type**</td>
87
+
<td>Numbers, strings, booleans, and tables.</td>
88
+
<td></td>
89
+
</tr>
90
+
<tr>
91
+
<td>**Common use cases**</td>
92
+
<td>Data that is only relevant to a single server session and that you can update instantly without worrying about persistence.</td>
93
+
<td>Example: Active buffs, temporary points, and ongoing quest progress that resets when the user leaves the experience.</td>
94
+
</tr>
95
+
<tr>
96
+
<td></td>
97
+
<td>Values that change frequently, like counters, timers, or state flags.</td>
98
+
<td>Example: A user's health bar that updates on each hit.</td>
99
+
</tr>
100
+
<tr>
101
+
<td></td>
102
+
<td>Avoiding rate limit restrictions for high-frequency operations in large active experiences.</td>
103
+
<td>Example: An experience with dozens of users interacting with the same object.</td>
104
+
</tr>
105
+
<tr>
106
+
<td></td>
107
+
<td>Data that drives game logic, like temporary variables or power-up states where quick access with no delay is essential.</td>
108
+
<td>Example: A user's current attack state or an enemy's current health, which needs to be accessible instantly and without the latency involved in calling external services like data or memory stores.</td>
109
+
</tr>
110
+
<tr>
111
+
<td></td>
112
+
<td>Multiplayer interactions that only matter within a single server.</td>
113
+
<td>Example: A shared objective in a co-op mission experience.</td>
Copy file name to clipboardExpand all lines: content/en-us/cloud-services/data-stores/index.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,8 @@ The `Class.DataStoreService` lets you store data that needs to persist between s
8
8
9
9
If you want to add granular permission control to your data stores and access them outside of Studio or Roblox servers, you can use [Open Cloud APIs for data stores](/cloud/reference/DataStore).
10
10
11
+
For temporary data that you need to update or access frequently, use [memory stores](./../memory-stores/index.md).
12
+
11
13
## Enabling Studio Access
12
14
13
15
By default, experiences tested in Studio can't access data stores, so you must first enable them. Accessing data stores in Studio can be dangerous for live experiences because Studio accesses the same data stores as the client application. To avoid overwriting production data, do not enable this setting for live experiences. Instead, enable it for a separate test version of the experience.
@@ -198,7 +200,7 @@ end
198
200
## Metadata
199
201
200
202
<Alertseverity="info">
201
-
Ordered data stores don't support [versioning and metadata](../../cloud-services/data-stores/managing-data-stores.md#versioning), so `Class.DataStoreKeyInfo|DataStoreKeyInfo` is always `nil` for keys in an `Class.OrderedDataStore|OrderedDataStore`. If you need to support versioning and metadata, use `Class.DataStore|DataStore`.
203
+
Ordered data stores don't support [versioning](../../cloud-services/data-stores/managing-data-stores.md#versioning) and metadata, so `Class.DataStoreKeyInfo|DataStoreKeyInfo` is always `nil` for keys in an `Class.OrderedDataStore|OrderedDataStore`. If you need to support versioning and metadata, use `Class.DataStore|DataStore`.
202
204
</Alert>
203
205
204
206
There are two types of metadata associated with keys:
Copy file name to clipboardExpand all lines: content/en-us/cloud-services/data-stores/managing-data-stores.md
+35-10Lines changed: 35 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ Manage your data using versioning, listing, and caching.
7
7
8
8
## Versioning
9
9
10
-
The functions `Class.GlobalDataStore:SetAsync()|SetAsync()`, `Class.GlobalDataStore:UpdateAsync()|UpdateAsync()`, and `Class.GlobalDataStore:IncrementAsync()|IncrementAsync()` create versioned backups of your data using the first write to each key in each UTC hour. Successive writes to a key in the same UTC hour permanently overwrite the previous data.
10
+
Versioning happens when you [set](./index.md#creating-data), [update](./index.md#updating-data), and [increment](./index.md#incrementing-data) data. The functions `Class.GlobalDataStore:SetAsync()|SetAsync()`, `Class.GlobalDataStore:UpdateAsync()|UpdateAsync()`, and `Class.GlobalDataStore:IncrementAsync()|IncrementAsync()` create versioned backups of your data using the first write to each key in each UTC hour. Successive writes to a key in the same UTC hour permanently overwrite the previous data.
11
11
12
12
Versioned backups expire 30 days after a new write overwrites them. The latest version never expires.
13
13
@@ -88,9 +88,7 @@ end
88
88
89
89
### Snapshots
90
90
91
-
The [Snapshot Data Stores Open Cloud API](/cloud/reference/DataStore#Snapshot-Data-Stores) lets you take a snapshot of all data stores in an experience once a day.
92
-
93
-
Before you publish any experience update that changes your data storage logic, make sure to take a snapshot. Taking a snapshot guarantees that you have the most recent data available from the previous version of the experience.
91
+
The [Snapshot Data Stores Open Cloud API](/cloud/reference/DataStore#Snapshot-Data-Stores) lets you take a snapshot of all data stores in an experience once a day. Before you publish any experience update that changes your data storage logic, make sure to take a snapshot. Taking a snapshot guarantees that you have the most recent data available from the previous version of the experience.
94
92
95
93
For example, without a snapshot, if you publish an update at 3:30 UTC that causes data corruption, the corrupted data overwrites any data written between 3:00-3:30 UTC. If you take a snapshot at 3:29 UTC, though, the corrupted data doesn't overwrite anything written before 3:29 UTC, and the latest data for all keys written between 3:00-3:29 UTC is preserved.
96
94
@@ -172,7 +170,7 @@ end)
172
170
173
171
### AllScopes Property
174
172
175
-
`Class.DataStoreOptions` contains an `Class.DataStoreOptions.AllScopes|AllScopes` property that lets you return keys from all [scopes](#scopes) in a list. You can then use the `Class.DataStoreKey.KeyName|KeyName` property of a list item for common data store operations like `Class.GlobalDataStore:GetAsync()|GetAsync()` and `Class.GlobalDataStore:RemoveAsync()|RemoveAsync()`.
173
+
`Class.DataStoreOptions` contains an `Class.DataStoreOptions.AllScopes|AllScopes` property that lets you return keys from all [scopes](#scopes) in a list. You can then use the `Class.DataStoreKey.KeyName|KeyName` property of a list item for common data store operations like [reading data](./index.md#reading-data) with `Class.GlobalDataStore:GetAsync()|GetAsync()` and[removing data](./index.md#removing-data) with`Class.GlobalDataStore:RemoveAsync()|RemoveAsync()`.
176
174
177
175
When you use the `AllScopes` property, the second parameter of `Class.DataStoreService:GetDataStore()|GetDataStore()` must be an empty string (`""`).
178
176
@@ -214,11 +212,11 @@ Use caching to temporarily store data from data stores to improve performance an
214
212
215
213
Caching applies to modifications you make to data store keys using:
-`Class.GlobalDataStore:GetAsync()|GetAsync()` to [read data](./index.md#reading-data).
216
+
-`Class.GlobalDataStore:SetAsync()|SetAsync()` to [create data](./index.md#creating-data).
217
+
-`Class.GlobalDataStore:UpdateAsync()|UpdateAsync()` to [update data](./index.md#updating-data).
218
+
-`Class.GlobalDataStore:IncrementAsync()|IncrementAsync()` to [increment data](./index.md#incrementing-data).
219
+
-`Class.GlobalDataStore:RemoveAsync()|RemoveAsync()` to [remove data](./index.md#removing-data).
222
220
223
221
`Class.DataStore:GetVersionAsync()|GetVersionAsync()`, `Class.DataStore:ListVersionsAsync()|ListVersionsAsync()`, `Class.DataStore:ListKeysAsync()|ListKeysAsync()`, and `Class.DataStoreService:ListDataStoresAsync()|ListDataStoresAsync()` don't implement caching and always fetch the latest data from the service backend.
224
222
@@ -235,3 +233,30 @@ All `Class.GlobalDataStore:GetAsync()|GetAsync()` calls that retrieve a value no
235
233
To disable caching and opt out of using the cache to retrieve the most up-to-date value from the servers, add the `Class.DataStoreGetOptions` parameter to your `Class.GlobalDataStore:GetAsync()|GetAsync()` call and set the `Class.DataStoreGetOptions.UseCache|UseCache` property to `false` to make your request ignore any keys in the cache.
236
234
237
235
Disabling caching is useful if you have multiple servers writing to a key with high frequency and need to get the latest value from servers. However, it can cause you to consume more of your [data stores limits and quotas](../../cloud-services/data-stores/error-codes-and-limits.md#limits), since `Class.GlobalDataStore:GetAsync()|GetAsync()` requests bypassing caching always count towards your throughput and server limits.
236
+
237
+
## Serialization
238
+
239
+
The `Class.DataStoreService` stores data in JSON format. When you save Lua data in Studio, Roblox uses a process called serialization to convert that data into JSON to save it in data stores. Roblox then converts your data back to Lua and returns it to you in another process called deserialization.
240
+
241
+
Serialization and deserialization support the following Lua data types:
242
+
243
+
-[Nil](../../luau/nil.md)
244
+
-[Booleans](../../luau/booleans.md)
245
+
-[Numbers](../../luau/numbers.md)
246
+
- You should not store the special numeric values `inf`, `-inf`, and `nan`, because these values don't conform to JSON standards. You can't access keys that contain these values with Open Cloud.
247
+
-[Strings](../../luau/strings.md)
248
+
-[Tables](../../luau/tables.md)
249
+
- Tables must only contain other supported data types
250
+
- Numeric keys are translated into strings if the length of the table is 0
If you try to store a data type that serialization doesn't support, you either:
254
+
255
+
- Fail in storing that data type and get an error message.
256
+
- Succeed in storing that data type as `nil`.
257
+
258
+
To debug why your data type is being stored as `nil`, you can use the `Class.HttpService.JSONEncode|JSONEncode` function. When you pass your Lua data type into this function, you receive it back in the format Roblox would have stored it with data stores, which lets you preview and investigate the returned data.
259
+
260
+
<Alertseverity="info">
261
+
Serialization doesn't happen when you use the [DataStore Open Cloud API](/cloud/reference/DataStore) because that data is already sent to Roblox in JSON format and doesn't need to be converted.
<sup>The **Invite Friends** pop-up and **Friend Referral Rewards** banner will become available in early 2025.</sup>
20
+
<br/><br/>
19
21
20
22
To implement a friend referral system, [set up a referral event](#set-up-a-referral-event) and [create referral rewards](#grant-referral-rewards). The `ReferredByPlayerId` property of `Class.Player:GetJoinData()|GetJoinData()` automatically populates for all types of invitations and gives you access to the user ID of the referring player. You can then access this data in the `Players.PlayerAdded` event to identify the inviter and grant rewards to the inviter and the invitee.
`Class.EditableImage` can be used in any `Datatype.Content` property which takes an image, such as `Class.ImageLabel.ImageContent` or `Class.MeshPart.TextureContent`. This is done by setting the content property to `Datatype.Content.fromObject(editableImage)`.
52
16
53
17
The `Class.EditableImage` coordinate system is relative to the top left of the
54
18
image:
@@ -57,8 +21,8 @@ description: |
57
21
- Bottom-right: `(Size.X - 1, Size.Y - 1)`
58
22
59
23
When you use `Class.AssetService:PromptCreateAssetAsync()` to publish an
60
-
object that has a property overridden by a child `Class.EditableImage`, the
61
-
editable image is published as an image and the overridden property is set to
24
+
object that has a `Datatype.Content` property which references an `Class.EditableImage`, the
25
+
editable image is published as an image and the property is set to
0 commit comments