Client vs server: the mental model
Here is the single most important idea in all of FiveM, the one that separates people who build working servers from people who get hacked in week one. Your code does not run in one place. It runs in two separate worlds that cannot see inside each other. One world is the player's game on their own PC. The other is the host machine everyone connects to. They each keep their own copy of your code and their own private memory, and the only way they ever communicate is by sending each other messages. Get this picture right and secure code becomes your default. Get it wrong and nothing you build will behave the way you expect.
Two worlds
When you write a FiveM resource, your code does not live in a single location. It is split across two machines that are physically far apart and never share memory.
The first is the client. That is the copy of the game running on a player's own computer, in their own house, on their own GPU. When someone joins your server, your client code is downloaded and runs there, on their machine, under their control.
The second is the server. That is the one host machine that every player connects to. It runs in a data center or on a box you rent. There is only one of it, and you own it. Players connect to it, but they never get to run code on it directly.
Picture two houses on opposite sides of a city, each with its own copy of the same instruction book. The client house follows its copy. The server house follows its copy. Neither house can walk into the other and read what is written on its notepad. The only way they coordinate is by mailing letters back and forth. Hold onto that picture for the whole lesson, because everything else is just a detail of it.
Vocabulary
- Client
- The copy of the game running on a single player's own PC. There is one client per connected player, and each player fully controls their own. Untrusted by default.
- Server
- The one shared host machine that every player connects to. There is exactly one, and you own it. Players never run code on it directly.
- Variable
- A named box that holds a value, like money = 500. A variable lives in the memory of whichever machine created it, and nowhere else.
- Authority (source of truth)
- The one side whose copy of a value is the real one. In FiveM the server is the authority for anything that matters: money, items, jobs. The client only ever holds a copy for display.
They cannot read each other's variables
This is the part beginners get wrong more than any other, so read it twice.
A variable is just a named box that holds a value. When your client code sets a variable, that box lives in the memory of the player's PC. The server has no idea it exists. When your server code sets a variable, that box lives on the host machine, and the player's PC has no idea it exists. Two houses, two notepads, no shared ink.
Here is the trap. Imagine your client code does this:
You have not learned to write this yet, and that is completely fine. Do not try to read it line by line or memorize it. Just look at the shape and follow the idea: a value is being set on the client. You will write real code for yourself in the very next module. For now you are only here to lock in the picture, not the syntax.
-- client.lua (runs on the player's PC)
local money = 500 -- a box on the PLAYER'S machine
print(money) -- prints 500, but this number is local and untrustedIt feels like you just gave the player $500. You did not. You created a box called money that holds 500 on the player's own computer, and nowhere else. The server has never heard of it. If your bank, your shop, and your job system all live on the server, they look at the server's real money value, which has not changed at all. Worse, the player can open their own files and write whatever number they like into that box, because it sits on their machine.
-- server.lua (runs on the host)
-- the server has NO variable called money from the client.
-- it keeps its own, completely separate, and that one is real.The rule to burn in: a value set on the client does not exist on the server, and a value set on the server does not exist on the client. When you want to "give a player money," you are really asking which house's notepad holds the real number. The answer is always the server's. The client's number is a copy at best and a lie at worst.
"Local" here has two meanings that both apply, and that is why it trips people up. A variable can be local to one machine (the client's box is not the server's box) and also local to one block of code (which you will meet in the variables lesson). For now, only the first meaning matters: a box created on one side is invisible to the other side, full stop.
How they talk: events
If the two worlds cannot share variables, how do they get anything done together? They send each other messages across the network. In FiveM those messages are called events.
An event is a named signal one side fires, carrying a small bit of data, that the other side listens for and reacts to. The client cannot reach into the server's memory, so instead it fires an event that means "hey server, please do this thing," and includes just enough information for the server to act. Think of it as the letter mailed between the two houses.
Here is a player clicking "buy" in a shop. The client cannot take the player's money itself, because the real money lives on the server. So it asks:
Read that diagram in plain words. The client says: "I want to buy the item with this id." That is all it sends, just the item id, across the network. The server is listening for the qu_shop:buy event. When the letter arrives, the server is the one that checks whether the player can actually afford it, whether the item is real, and whether they are even near the shop. Then the server changes the real money and the real inventory, and mails a letter back telling the client what to show on screen.
Notice what the client did not do. It did not subtract money. It did not hand over an item. It only asked. The asking and the deciding happen on two different machines on purpose.
Why the server is always in charge
Now the reason this split exists, and why it is non-negotiable.
The client runs on the player's own PC, which means the player has total control over it. They can open the downloaded files, read every line, change values, and even rewire your code to lie. A determined cheater treats your client code as a suggestion, not a rule. So you can never trust a single thing the client says about itself. If the client claims "I have $1,000,000" or "I already paid for this car," it might be telling the truth, or it might be a player who edited their files. You have no way to know.
The server is different. It runs on your machine, behind your door. Players connect to it but cannot read or change its code. Whatever the server decides is final, and a cheater cannot touch it. That is exactly why the server, and only the server, is allowed to be the authority for anything that matters.
So the law of every FiveM server you will ever build is this: money, items, and every important decision must be checked and changed on the server. The client is the display layer. It draws the menu, reads the keypress, and shows the notification. It asks. The server is the rule keeper. It validates the request and owns the real numbers. It decides. When you find yourself writing code that changes something valuable, stop and ask which side it is on. If the answer is the client, you have just handed cheaters the keys.
Why this is the security backbone
Almost every FiveM exploit you will ever read about comes down to one mistake: a server trusted something the client said without checking it. A shop that takes the client's word for the price. A bank that lets the client send "deposit $50,000" with no verification. Once you internalize "the server validates everything, the client only asks," you are already writing more secure code than most beginners ever do. You do not need to memorize a list of exploits. You need this one habit.
Common beginner mistakes
These two errors are almost a rite of passage. Knowing them now saves you a confusing afternoon later.
| Symptom | Fix |
|---|---|
I set the player's money on the client but it resets | The client value is a local copy on the player's PC and is untrusted, so nothing real changed. The bank and shop read the server's number, which you never touched. Change money on the server, the source of truth, then send an event to the client to display the new amount. |
attempt to call a nil value (a client-only function called on the server) | That function only exists on one side. nil means "this name has no value here." Look at which file the call is in: code in a client file runs on the player's PC, code in a server file runs on the host. Call the function from the side it actually lives on. |
A player should get $500 for a job. Which side adds the money, and why?
The server adds the money. Money is a value that matters, so its real copy lives on the server, the source of truth. The client cannot be trusted to change its own balance, because the player controls their own PC and could simply write any number they like. The correct flow is: the client fires an event like "I finished the job," the server checks that the player really did finish it, and then the server adds the $500 to the real balance and sends an event back so the client can show the new total on screen. The client asks, the server decides and changes the number.
Try it yourself
What you can do now
- Explain that FiveM code runs in two separate worlds: the client on each player's PC, and the one shared server you own.
- State the rule that a variable set on one side does not exist on the other side, and spot the beginner trap of setting money on the client.
- Describe how the two sides communicate: not by sharing memory, but by firing events across the network.
- Explain why the server is the only trusted authority, and why money, items, and important decisions must be checked there.
- Sort the checks in a feature into client (input, display, asking) and server (permission, cooldown, deciding).
You now hold the mental model the entire platform runs on. Two worlds, no shared memory, the client asks and the server decides. Every secure resource you ever write is just this idea applied carefully. Next you stop reading and start writing: in "Your first line of Lua" you will write your very first real line of code and watch it run, no server needed. That lesson kicks off the Lua from zero module.