GlobalStockService | Manage Global Stocks Across Servers with Forced Overrides & Auto-Restock (v1.0.8)

GlobalStockService

A Roblox module for managing global stock across servers using DataStoreService and MemoryStoreService. Supports forced stock overrides, automatic restocking, random stock prediction based on a global key, callbacks for stock changes

The GlobalStockService module is NOT related to financial stocks or the stock market.

link: GitHub - V1nyI/roblox-GlobalStockService: A Roblox module for managing **global synchronized stocks** like shop restocks, timed events, and forced overrides across all servers

https://create.roblox.com/store/asset/102142312665442/GlobalStockService


Features

  • global stock generation with a shared global key
  • Automatic periodic restocking with configurable intervals
  • Forced stock overrides with expiration via MemoryStoreService
  • Callbacks for stock changes and forced stock updates
  • Safe update retries and key rotation support
  • Debug logging and version update notifications
  • Day-of-week and date range restrictions for stock availability


Update logs, Version “v1.0.8”

  • Stock types (current types: “normal”, “datelimited”, “dayofweeklimited”)
  • Date range restrictions
  • Day-of-week restrictions

Example usage:

local GlobalStockService = require(path.to.GlobalStockService)

--// Example 1: Normal Stock
GlobalStockService.CreateStock(
	"NormalStock", -- stock name
	{
		{name = "Apple", chance = 80, minAmount = 1, maxAmount = 5},
		{name = "Banana", chance = 50, minAmount = 1, maxAmount = 3},
	}, -- items
	1, -- minItems
	2, -- maxItems
	60 -- restockInterval in seconds
)

--// Example 2: DateLimited Stock
GlobalStockService.CreateStock(
	"HolidayStock",
	{
		{name = "CandyCane", chance = 100, minAmount = 1, maxAmount = 2},
		{name = "GiftBox", chance = 60, minAmount = 1, maxAmount = 1},
	},
	1, -- minItems
	2, -- maxItems
	200, -- restockInterval
	"DateLimited", -- type
	{
		start = {year = 2025, month = 12, day = 23},
		["end"] = {year = 2025, month = 12, day = 31}
	} -- date range
)

--// Example 3: DayOfWeekLimited Stock
GlobalStockService.CreateStock(
	"WeekendStock",
	{
		{name = "Chocolate", chance = 90, minAmount = 1, maxAmount = 4},
		{name = "Juice", chance = 70, minAmount = 1, maxAmount = 2},
	},
	1, -- minItems
	2, -- maxItems
	5, -- restockInterval
	"DayOfWeekLimited", -- type
	{
		days = {"Thursday", "Sunday"}
	} -- days of the week
)

-- Callback to see when stocks change
GlobalStockService.OnStockChanged(function(stockName, oldStock, newStock, time)
	print("Stock changed:", stockName)
	print("Old stock:", oldStock)
	print("New stock:", newStock)
	print("Time:", time)
end)
GlobalStockService just added day-of-week and date-range restrictions for stock availability! How do you feel about this update?
  • Useful
  • Neutral
  • Confusing
  • Don’t like it
0 voters

Installation

  1. Copy GlobalStockService.lua into your Roblox project (Only in ServerScriptService) do not expose this module to any client.
  2. Require it in your script:
local GlobalStockService = require(path.to.GlobalStockService)

Basic Usage

Create a stock configuration and start its update loop:

local stockItems = {
    {name = "ItemA", chance = 50, minAmount = 1, maxAmount = 3},
    {name = "ItemB", chance = 30, minAmount = 2, maxAmount = 5},
    {name = "ItemC", chance = 80, minAmount = 1, maxAmount = 1},
}

local myStock = GlobalStockService.CreateStock("MyShopStock", stockItems, 1, 3, 600)

local currentStock = GlobalStockService.GetCurrentStock("MyShopStock")
for _, item in ipairs(currentStock) do
    print(item.name, item.amount)
end

Forced Stock Overrides

Force the next stock to a specific list for a defined number of restocks:

local forcedStock = {
    {name = "SpecialItem", amount = 10}
}

GlobalStockService.ForceNextStock("MyShopStock", forcedStock, 2)

-- Clear forced stock override:

GlobalStockService.ClearForcedStock("MyShopStock")

Event Callbacks

Subscribe to stock change events:

GlobalStockService.OnStockChanged(function(stockName, oldStock, newStock, restockTime)
    print("Stock changed for", stockName)
end)

Subscribe to forced stock change events:

GlobalStockService.OnStockForceChanged(function(stockName, oldStock, newStock, timer)
    print("Forced stock changed for", stockName)
end)

Subscribe to forced stock expiration events:

GlobalStockService.OnForcedStockExpired(function(stockName)
    print("Forced stock expired for", stockName)
end)

Advanced Usage

Rotate the global key manually

local success, newKeyOrError = GlobalStockService.ForceRotateGlobalKey()
if success then
    print("Global key rotated successfully")
else
    warn("Failed to rotate global key:", newKeyOrError)
end

Enable or disable debug logging

GlobalStockService.SetDebug(true) -- Enable debug logs
GlobalStockService.SetDebug(false) -- Disable debug logs

API Overview

  • CreateStock(name, items, min, max, interval) - Create and start a new stock configuration
  • GetCurrentStock(name) - Get current stock for a stock name
  • ForceNextStock(name, list, restocks) - Force next stock list for a given number of restocks
  • ClearForcedStock(name) - Clear forced stock override
  • OnStockChanged(callback) - Subscribe to normal stock change events
  • OnStockForceChanged(callback) - Subscribe to forced stock change events
  • OnForcedStockExpired(callback) - Subscribe to forced stock expiration events
  • ForceRotateGlobalKey() - Manually rotate the global key
  • StopStock(name) - Stop the stock update loop for a stock
  • SetDebug(enabled) - Enable or disable debug logging

License

MIT - see LICENSE for details.


GitHub: V1nyI

Is this Module useful?
  • Yes
  • Maybe
  • No
0 voters
25 Likes

I was initially confused as to what the name means, and if you are referring to the financial “stock”,

You should start the post by defining what stock means, might clear up some people’s confusion. Other than that, very thoughtful module! I can see a lot of games using this.

Hello! I apologize for the misunderstanding, I’ve added some text to clarify that this isn’t that kind of stock, Thank you for pointing it out!

This module isn’t just for basic shops, you can use it for all sorts of synced, rotating, and event-based content across your entire game:

  • Global Shops - Automatically restocking every X minutes/hours with the same items for every server
  • Limited-Time Events - Force special items into stock for a set number of restocks (perfect for holiday or update events)
  • Rotating Cosmetics - Daily or weekly rotations of skins, hats, or outfits that all players see at the same time
  • Traveling Merchants - NPCs that appear periodically with unique, randomized stock

If it needs global synchronization, randomness, and event control, this module can probably handle it

Working on something that will make shop schedules feel a lot more.. alive

Update logs, Version “v1.0.8”

  • Stock types (current types: “normal”, “datelimited”, “dayofweeklimited”)
  • Date range restrictions
  • Day-of-week restrictions

Example usage:

local GlobalStockService = require(path.to.GlobalStockService)

--// Example 1: Normal Stock
GlobalStockService.CreateStock(
	"NormalStock", -- stock name
	{
		{name = "Apple", chance = 80, minAmount = 1, maxAmount = 5},
		{name = "Banana", chance = 50, minAmount = 1, maxAmount = 3},
	}, -- items
	1, -- minItems
	2, -- maxItems
	60 -- restockInterval in seconds
)

--// Example 2: DateLimited Stock
GlobalStockService.CreateStock(
	"HolidayStock",
	{
		{name = "CandyCane", chance = 100, minAmount = 1, maxAmount = 2},
		{name = "GiftBox", chance = 60, minAmount = 1, maxAmount = 1},
	},
	1, -- minItems
	2, -- maxItems
	200, -- restockInterval
	"DateLimited", -- type
	{
		start = {year = 2025, month = 12, day = 23},
		["end"] = {year = 2025, month = 12, day = 31}
	} -- date range
)

--// Example 3: DayOfWeekLimited Stock
GlobalStockService.CreateStock(
	"WeekendStock",
	{
		{name = "Chocolate", chance = 90, minAmount = 1, maxAmount = 4},
		{name = "Juice", chance = 70, minAmount = 1, maxAmount = 2},
	},
	1, -- minItems
	2, -- maxItems
	5, -- restockInterval
	"DayOfWeekLimited", -- type
	{
		days = {"Thursday", "Sunday"}
	} -- days of the week
)

-- Callback to see when stocks change
GlobalStockService.OnStockChanged(function(stockName, oldStock, newStock, time)
	print("Stock changed:", stockName)
	print("Old stock:", oldStock)
	print("New stock:", newStock)
	print("Time:", time)
end)

Thank you for making this. My game already had a similar global stock system, but this gives me so much more room to expand on concepts like traveling merchants. I think you should make a documentation for it, but until then, I will be sure to use this in all stock-related systems in my game!

This is the second stock module I have seen on the forum, the first was 10$ and the guy who made it was kind of a bum. I’m glad to see a new free one appear and from someone who is actually kind.

I am thinking about making a game along the grow a ____, so this will be VERY useful! Good job man!

Exactly what I’ve been looking for my GAG series. Thank you very much, I’ll make a video on this.

1 Like

Module is now available on roblox creator store: https://create.roblox.com/store/asset/102142312665442/GlobalStockService

This seems pretty cool. Anyone got examples of stuff they set up with this?

Hi!

I have made a “Global weather” tutorial with GlobalStockService: [Tutorial] Make Global Weather in Roblox with GlobalStockService

Hello! While I testing your module I found a bug, .CreateStock() I was set minItems = 3 and maxItems = 4 but when running sometimes returns only 2 items in the Stock or is it my fault?

Script:

local GlobalStockService = require(game.ReplicatedStorage.GlobalStockService)
GlobalStockService.CreateStock(
	"SpecStock",
	{
		{name = "Main Stock", chance = 100, minAmount = 1, maxAmount = 1},
		
		{name = "One", chance = 50, minAmount = 1, maxAmount = 1},
		{name = "Two", chance = 50, minAmount = 1, maxAmount = 1},
	},
	3,
	4,
	30
)

GlobalStockService.SetDebug(true)
GlobalStockService.OnStockChanged(function(stockName, oldStock, newStock, time)
	print(`New {stockName}:`, newStock)
end)

Image:

By the way could you make Stock able to stock at fixed Items? Like minItems = 3 and maxItems = 3 then it will always return 3 Items.

1 Like

Hi! Thanks for pointing that out.

I’ve patched it, so it should now behave as expected, Thanks again for testing and letting me know!

This is really good btw

Just a question: Is there any way to see when the shop will next restock? Or when it was last restocked, since I want to implement a timer to show the players when the next restock is.

I may have missed it as I’ve only been using this for the past 5 minutes lol

Hey so this is a great module, but there are better ways to get a global stock system.

The best way would be using Random.New() with a global seed.

local function GenerateStock()
	local CurrentTime = os.time()
	local TimeInterval = 300
	local TimeSeed = CurrentTime - (CurrentTime % TimeInterval)
	LastTimestamp = TimeSeed
	
	local Random = Random.new(TimeSeed) --makes sure the random is same for every server
	
	local SortedList = {}
	
	for ItemName, Data in (BlocksList) do
		if Data.NotSellable then continue end
		table.insert(SortedList, {
			Name = ItemName,
			Data = Data
		})
	end

	table.sort(SortedList, function(a, b)
		return a.Data.Chance > b.Data.Chance
	end)
	local Stock = {}
	
	for _, Item in pairs(SortedList) do
		local ItemName = Item.Name
		local MaxStock = Item.Data.MaxStock
		local ItemChance = Item.Data.Chance
		
		local Entry = {
			Name = ItemName,
			Stock = 0,
		}
		
		local Chance = Random:NextNumber(0, 100)
		if Chance <= ItemChance then
			Entry.Stock = StockRounding(Random:NextInteger(1, MaxStock), MaxStock)
		end
		
		table.insert(Stock, Entry)
	end
	
	return Stock
end

The Pros from said system:

  • Doesn’t use datastore to save data (saves requests/more reliable
  • Each server has the same stock without having to communicate

What I’d do:

  • If you wanted a forced restock I’d have a MessagingService call (and maybe memory stores)
  • To stop predictions of the stock I’d have the seed be hashed/changed using an algorithm

But nonetheless it’s a great resource

Thanks a lot man this works perfectly!

Module is still super useful however I don’t need anything super in-depth, literally just restocking every 24 hours.

Hey! I just updated the module to v1.2.0

You can now use:

  • GetNextRestockTime - to see the timestamp of the next restock
  • GetTimeUntilRestock - to see how much time is left until the next restock

Example:

local GSS = require(path.to.GlobalStockService)

GSS.CreateStock("Shop", {
	{name = "sword", chance = 100, minAmount = 1, maxAmount = 1}
}, 1, 1, 100) -- stockName, items, minItems, maxItems, restockInterval

-- Print next restock time and time left every 3 seconds
while task.wait(3) do
	local nextRestock = GSS.GetNextRestockTime("Shop")
	local timeLeft = GSS.GetTimeUntilRestock("Shop")
	
	print("Next restock at:", os.date("!%Y-%m-%d %H:%M:%S", nextRestock)) -- UTC
	print("Time left:", timeLeft, "seconds")
end

Hi! Thanks for your thoughtful suggestion!

Anything to help, I’m a firm believer knowledge should be shared not gate kept.

2 Likes