DataStore Synchronization for Infinite Craft

I’m recreating Infinite Craft in Roblox and hitting DataStore request limits with just 3 players. Need advice on optimization.

Current Implementation:

  • Using DataStore to save:
    • Global combinations (saved on each new discovery + auto-save every 5min)
    • Emoji mappings (checked/saved for each new element)
    • Element combinations store (checked for each combination attempt)

The Issue:

With just 3 players actively combining elements, we’re hitting DataStore request limits. Each combination attempt requires multiple DataStore interactions:

  1. Checking if combination exists
  2. Saving new combinations
  3. Checking/saving emoji mappings
  4. Plus periodic auto-saves of the global state

Current Rate Limiting:

  • 450 requests/minute per server
  • 32 requests/minute per player

Even with these limits in place, we’re still hitting DataStore caps. Has anyone solved similar high-frequency DataStore usage issues?

What We’ve Considered:

  1. Batch Updates:
  • Could collect changes and save less frequently
  • BUT: Other servers need to know about new combinations immediately
  • Problem remains: How do servers stay in sync with delayed saves?
  1. MemoryStore as Buffer:
  • Could use MemoryStore for temporary storage
  • BUT: Still need DataStore for persistence
  • Doesn’t reduce the fundamental number of operations needed

is every combination saved on a module script/manually made or is it like automatically generated?

The combinations are automatically generated using the Gemini AI API:

  1. When players try to combine elements, the system:
  • First checks if this combination already exists (saved in DataStore)
  • If it exists, returns the saved result
  • If it’s new, calls the AI to generate a result
  1. The AI generation happens in two steps:
  • First generates a word result (like “steam” from “water + fire”)
  • Then generates an emoji to go with it (like “:dash:”)
  • Combines them into “:dash: Steam”
  1. Storage:
  • All successful combinations are saved to DataStore
  • Emoji mappings are saved separately to ensure consistency
  • These saved combinations become the “global discoveries”

maybe instead of saving the emoji, just generate the emoji each time they join

i don’t know if it would be unoptimized since i have never used it

Bumpity Bump! Need help! Still don’t know where to go form here.

I assume the issue here is you are requesting GetAsync and SetAsync too fast which quickly builds up rate limits (60 + 10 * (player count)), instead of creating multiple keys for each discovery, you can try creating a key for a player (ex. “Player_” … UserID) and loading this key whenever the player first joins the game. You can make changes to this key (assuming it is a table) and save it whenever the player is leaving.

I suggest using ProfileService for this as it is a great module for managing datastores.

The problem isn’t with player data saves/loads (which your solution would help with). The issue is with the global combinations system:

When any player anywhere combines “Water + Fire”:

  1. We need to check if this combination exists globally
  2. If it’s new, we save it so ALL players across ALL servers know about it
  3. Other players need to know about new combinations in real-time(ish)

So while ProfileService is great for player data, it doesn’t solve our main problem:

  • Server A’s player discovers “Water + Fire = Steam”
  • Server B’s player tries “Water + Fire” right after
  • Server B needs to return “Steam” too, not generate a new result

We’re hitting limits because:

  1. Every combination attempt needs to check global combinations
  2. New discoveries need to be immediately available to all servers
  3. Multiple servers accessing/writing to the same global combination table

Maybe try using MessagingService.
I have tried doing a pet exist system like this once: Public Data Saving
You could look into the scripts, i used datastoreservice with :UpdateASync()
With UpdateAsync you could check if a value exists + directly overwrite it.
And for MessagingService. I used it to tell every server that a new value has been insterted/updated.
This module has been made in 2024 Juli, so dont expect much of it, but maybe the technique will help. I hope this helps! ^^

Sorry for the previous reply, I believe the only way you can do this is to implement rate limits (ex. allow 1 combination to be made every second (which wouldn’t make much of a difference if players arent constantly spamming), if the user is attempting to make a combination but there is still a rate limit it will wait until the rate limit is complete and reject new combinations until the current task is done.)

  1. Yes you can use batching for this but if the server crashes the data would be lost.
  2. You can also use MemoryStores for temporary cache, but if all servers are down the data would be lost again.
  3. Another option would be MessagingService, but if player 1 rejoins while player 2 is still on que they will still reclaim it since the data from MessagingService wasn’t recieved.

I suggest making the game singeplayer and implementing a global chat system, this way you can maximize rate limits.