DISCLAIMER
This is one of the many ways that Grow a Garden might be using for their stock system. I cannot guarantee that this is identical to how Grow a Garden does it, but the overall simplicity in this approach makes it feasible compared to other approaches
I have tested this approach both theoretically and practically, and concluded that it is reliable enough
1. Brief Introduction to Grow a Garden’s Stock System
Grow a Garden has various kinds of shops that you can purchase items out of. However, all of those items have a limited stock, and will restock after 5 minutes. This is one of the main premise of Grow a Garden that makes it the biggest game of all time.
2. The Approaches
As i have pointed out, there are many ways you can approach this. So lets explore them one by one:
If you have other approaches in mind, feel free to post it!
- HttpService
Reliable, controlled, but complex and could exhaust your HTTP quota - MessagingService
Unreliable-ish, not guaranteed, easily event-driven, but completely unneccessary for this case - Using the global server time
Reliable, simple, guaranteed
From those you would see where I’m going with this…
3. The Procedure
For the global server time, we’ll use Workspace:GetServerTimeNow(), which is shared across all servers.
To get when the next and the previous interval is:
next = (time + (interval - (time % interval)))
previous = time - (time % interval)
And to get if the current time is on the interval, we’ll just check if its divisible by the interval
time % interval == 0
To do the random but global stocks, we need a set seed. We can use the time for that, but that’ll make our stocks easily predictable. To make it harder to predict, we can simply use a hash cryptography function, for simplicity, below is a VSH hash:
local function hash(str: string): number
local hash = 2166136261
for i = 1, #str do
local c = str:sub(i, i)
local byte = string.byte(c)
hash = bit32.bxor(hash, byte)
hash = (hash * 16777619) % 2 ^ 32
end
return hash
end
Here’s a sample code I made in like 5 minutes based on my own code
local INTERVAL = 5 * 60 -- 5 minutes
local KEY = 'supersecretkey' -- The key to hash your seeds
-- Time Utilities
local function getNextIntervalTime(now: number, interval: number)
return (now + (interval - (now % interval)))
end
local function getPreviousIntervalTime(now: number, interval: number)
return now - (now % interval)
end
local function isOnInterval(time: number, interval: number)
return time % interval == 0
end
local function hash(str: string): number
local hash = 2166136261
for i = 1, #str do
local c = str:sub(i, i)
local byte = string.byte(c)
hash = bit32.bxor(hash, byte)
hash = (hash * 16777619) % 2 ^ 32
end
return hash
end
-- Runs every interval
local function onInterval(time: number)
local rng = Random.new(hash(`{KEY}/{time}`))
-- Then do your stocks rng...
local stock1 = rng:NextInteger(0, 10)
local stock2 = rng:NextInteger(0, 10)
-- ...
end
local now = workspace:GetServerTimeNow()
local tickTime = if isOnInterval(now, INTERVAL)
then now
else getPreviousIntervalTime(now, INTERVAL)
onInterval(tickTime) -- Make sure new servers get the same deal
while true do
now = workspace:GetServerTimeNow()
local nextTime = getNextIntervalTime(now, INTERVAL)
task.wait(nextTime - now)
onInterval(nextTime)
end
The key serves as a way to secure the seed from being predictable, but it should be the same across all servers.
Footnotes
This was a rushed topic, please let me know if there’s anything wrong here

