Skip to main content
TRACK B·DATA AND PERSISTENCE·Verified June 2026 · Lua 5.4 · ox_lib 3.x
Learning with an AI assistant?
Copies this lesson plus 2026 ground rules (no lua54 'yes', Cfx.re Portal, correct callback signatures) as a ready-to-paste mentor prompt.

Persistence without a database: the KVS

Most beginners think the only way to make data survive a restart is a database. It is not. FiveM ships a per-resource key-value store, the KVS, that writes small values straight to disk for you. No schema, no connection string, no SQL. One caution up front: the KVS stores values as plain, unencrypted data on the server's disk. Never put secrets in it (no passwords, API keys, Tebex/Discord tokens, or webhook URLs) -- those belong in environment-controlled config, not the KVS. In this lesson you build a counter that climbs every time you run a command, then survives a full server restart untouched. Once it works, you will know exactly when the KVS is the right tool and when it is the wrong one.

You'll build
A server resource that increments a counter on command and reloads the same number after a full server restart, proving the value lives on disk and not just in memory.
Time
~18 minutes
You need
A local FiveM practice setup you can restart, a text editor, and the heal-command or natives-toolbox resource already working so you are comfortable with RegisterCommand on the server.
You'll learn
The built-in key-value store, the typed get and set natives, deleting and listing keys, and the exact line where KVS stops being enough and you reach for MariaDB plus oxmysql instead.
BEFORE YOU START

Build it

Make the resource folder

The server has one folder for this lesson.

Inside your server's resources folder, create this folder:

code
resources/qu_kvs_counter

Create the files

Every file named in the manifest exists.

Create this exact file layout:

code
resources/qu_kvs_counter/
fxmanifest.lua
server.lua

Write fxmanifest.lua

FiveM knows which files to load.

Open fxmanifest.lua and paste this:

code
fx_version 'cerulean'
game 'gta5'

server_script 'server.lua'

The KVS natives are available in Cfx scripting contexts, but this lesson deliberately uses them in a server_script so the saved counter is controlled by the server and not by a player's local client store. There is no lua54 'yes' line; Lua 5.4 is the only Lua runtime.

Write the lesson code

The counter reads from disk, increments, and writes back.

Open server.lua and paste this:

code
local KEY = 'visit_count'

-- Read the saved number on startup. An unset integer key reads as 0.
local count = GetResourceKvpInt(KEY)
print(('[qu_kvs_counter] loaded count from KVS: %d'):format(count))

RegisterCommand('countup', function()
count = count + 1
SetResourceKvpInt(KEY, count)
print(('[qu_kvs_counter] count is now %d (saved to disk)'):format(count))
end, true)

RegisterCommand('countshow', function()
print(('[qu_kvs_counter] current count: %d'):format(GetResourceKvpInt(KEY)))
end, true)

RegisterCommand('countreset', function()
DeleteResourceKvp(KEY)
count = 0
print('[qu_kvs_counter] count deleted from KVS, back to 0')
end, true)

Start and test it

The number climbs, then survives a full restart.

Open server.cfg and add this line:

code
ensure qu_kvs_counter

Save, then run these two lines in the txAdmin Live Console, in order. refresh makes the server notice the new folder you just created; ensure then starts it:

code
refresh
ensure qu_kvs_counter

(If the resource was already running from a previous attempt, restart qu_kvs_counter reloads it instead. But a brand-new resource needs refresh first, or the console replies that it cannot find the resource.)

Run the counter up three times, then check it:

code
countup
countup
countup
countshow

Now the real proof: a cold boot of the whole server, the thing a database is supposed to survive. This is NOT restart qu_kvs_counter. Do a real full restart of the FXServer process: in the txAdmin web panel, open the dashboard and click Restart (the server-control button at the top), or in a raw console window press Ctrl+C to stop FXServer and then launch it again. When the resource loads, watch the startup line:

The number came back as 3 with no database anywhere. That is the KVS doing its job.

Keep reading the full lesson

Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.

Still ahead in this lesson
  • How it works
  • Common mistakes
  • What you can do now
  • Try it yourself

The remainder of Persistence without a database: the KVS is available to FiveM School members.