FiveM KVP storage: SetResourceKvp and GetResourceKvpString guide
Save client settings without a database using FiveM KVP: SetResourceKvp, GetResourceKvpString, SetResourceKvpInt, DeleteResourceKvp, json.encode for tables, and its limits.
You want a script to remember a setting between sessions: the volume of a radio, a HUD position, the last tab a player used in a menu. A database table per setting is too much, and a file is not possible on the client. FiveM has a built-in key value store for exactly this, called KVP.
This article covers the functions, how to store tables, where the data lives, and what you must not put in it.
The functions
KVP stores a value under a key. Strings, integers and floats have their own functions:
| Task | Function |
|---|---|
| Save a string | SetResourceKvp(key, value) |
| Read a string | GetResourceKvpString(key) |
| Save an integer | SetResourceKvpInt(key, value) |
| Read an integer | GetResourceKvpInt(key) |
| Save a float | SetResourceKvpFloat(key, value) |
| Read a float | GetResourceKvpFloat(key) |
| Remove a key | DeleteResourceKvp(key) |
SetResourceKvp('volume', '0.6')
local volume = GetResourceKvpString('volume') -- '0.6', or nil if it was never saved
SetResourceKvpInt('hud:x', 40)
local x = GetResourceKvpInt('hud:x') -- 40, or 0 if it was never saved
DeleteResourceKvp('volume')Note the difference in "not found": the string reader gives nil, while the number readers give 0. If 0 is a valid value for your setting, store it as a string, or keep a second key that says the value was set.
Always provide a default
A new player has nothing saved yet, so read with a fallback:
local function getVolume()
local saved = GetResourceKvpString('volume')
return saved and tonumber(saved) or 0.5
endStoring tables with json.encode
KVP only knows strings and numbers. For a table, serialise it:
local settings = { volume = 0.6, hud = { x = 40, y = 12 }, tabs = { 'home', 'bank' } }
SetResourceKvp('settings', json.encode(settings))local raw = GetResourceKvpString('settings')
local settings = raw and json.decode(raw) or { volume = 0.5, hud = { x = 0, y = 0 }, tabs = {} }json is available in every FiveM Lua resource, with no import. Always handle the case where the key does not exist, and keep the stored table small: this is not a place for big lists.
Tip: put a version in the table, such as
version = 1. When you change the layout in a later update, you can read the old shape and convert it instead of crashing on a missing field.
Where it is stored
Client KVP lives on the player's computer, in the FiveM data folder, not on your server. It is kept per resource and per server: the same key in the same resource on another server is a different value, and two resources can both use the key volume without touching each other.
That has three consequences:
- Reinstalling FiveM or wiping its data folder can erase it. If a player is told to clear the cache, have them keep the KVP data when they can.
- A player who plays from two PCs has two separate sets of settings.
- You cannot read a player's KVP from the server. It is a client feature.
Warning: the data is a plain local file under the player's control. A player can edit it, delete it or copy it to a friend. Never keep anything the server must trust there: money, items, permissions, cooldowns, ban flags or progress with a reward.
Server KVP
The same functions exist on the server. There the data is saved on the server's disk in the server data folder, per resource, and survives restarts:
-- server
SetResourceKvp('last_restart', tostring(os.time()))
local last = GetResourceKvpString('last_restart')It is handy for small global values that do not deserve a SQL table: a counter, a feature flag toggled with a command, the date of the last event. For anything with many rows, or that you want to query, edit by hand or back up with the rest of your data, use the database (oxmysql queries guide). Server KVP is not visible in your SQL tool, and backing up the server needs the data folder as well.
Writing a lot of keys
Every SetResourceKvp writes to disk. If you save many keys at once, for example when a player closes a settings menu, FiveM offers a variant that does not write immediately and a call that flushes the batch:
SetResourceKvpNoSync('a', '1')
SetResourceKvpNoSync('b', '2')
SetResourceKvpNoSync('c', '3')
FlushResourceKvp()For a handful of keys saved now and then, the normal functions are fine. Do not write on every frame, for example while a slider is dragged: save when the player lets go.
Listing keys
To find all keys that start with a prefix, use the find functions:
local handle = StartFindKvp('hud:')
if handle ~= -1 then
local key
repeat
key = FindKvp(handle)
if key then print(key, GetResourceKvpString(key)) end
until not key
EndFindKvp(handle)
endPrefix your keys with a short name for what they are (hud:x, hud:y) so this stays easy.
When to use something else
| You need to store | Use |
|---|---|
| A UI preference or a local setting | Client KVP |
| A small global value on the server | Server KVP |
| Player data the server relies on | A database table |
| Data shared between players | Server database, or a state bag for live state |
Checklist
| Symptom | Fix |
|---|---|
Setting is nil for new players |
Read with a default value |
Saved 0 looks like not saved |
Number readers return 0 when missing: store as string, or add a flag |
| Need to save a table | json.encode to store, json.decode to read |
| Players edit their saved values | Do not store anything the server trusts in KVP |
| Setting lost on another PC or server | KVP is per computer and per server: expected |
| Many writes in a row | Save once when the player finishes, or use SetResourceKvpNoSync with FlushResourceKvp |
Quick answers
Where is FiveM KVP data stored?
Client KVP is saved on the player's own PC, in the FiveM data folder, per resource and per server. Server KVP is saved on the server's disk, in the server data folder.
Can I store a table in KVP?
Not directly. Encode it with json.encode(table), store the string, and read it back with json.decode.
Is KVP safe for money, inventory or bans?
No. A client can edit its own KVP data, so only keep preferences there, such as a volume or a UI layout. Anything with value belongs in the server database.
Scripts that skip this problem
Clothing DesignerDesign clothing inside FiveM β brush, layers, image import and AI β then wear it.View script β
Mic PhoneA foldable phone that unfolds into a tablet and carries onto a player's real phone.View script β
Hookah SystemPlaceable hookahs and lounge furniture with 50+ flavours and effects.View script β