"Let the server decide the important values" — and if there is no server?
Game security advice tends to end on the same sentence. "Values that matter, like currency or scores, should not be trusted from the client; the server should have the final say."
That is correct. We have said it more than once ourselves.
The problem is what comes after. For a team without a backend, that advice amounts to "rebuild what you have." Standing one up means server costs, an account system, incident response, privacy handling, and someone to keep it running. For a game that is mostly single-player, that bill can exceed what it buys.
So this article asks a different question. Having decided not to run a server, how far can you get, and what do you have to give up?
First, honestly: what you cannot do without a server
One thing to settle before starting. While the client has the final say, there is no decisive defence.
If the game decides "5,000 gold" on the device and nothing outside can check that decision, an attacker willing to spend the time will eventually make that value whatever they want. Changing the storage format, signing it, hiding it in memory — the same holds. The verifying code is on that same device.
So framing the goal as "prevent" fails here. Three realistic goals instead:
- Raise the cost — from "open the save in a text editor" to "analyse a binary"
- Leave traces — so you can tell, even later, that manipulation happened
- Stay able to restore — keep a path back to a correct state when something surfaces
Those three alone filter out most casual manipulation. How to protect the save file itself is covered in game save file tampering. This article picks up after that.
Three that work especially well when there is no server
1. Save rollback — when the undo button is free
Copy the whole save aside, and restore it whenever the outcome is not to your liking.
- Pull a gacha, restore if the result is poor, pull again
- Spend a consumable, restore, and un-spend it
- Die in a hard section, restore, and erase the penalty
What makes this one awkward is that nothing has to be tampered with. A legitimate save is legitimately restored, so integrity checks and encryption do not catch it. The signature verifies fine — the save is real.
2. Device clock manipulation — removing the wait
Move the device clock forward and any design that spends time falls apart.
- Collect a daily reward several times a day
- Finish construction or growth timers instantly
- Reset cooldowns
System.DateTime.Now reads the device clock. With no server, there is nothing to check that clock against.
3. Cloud save conflicts — hopping between devices and keeping the better one
With cloud saves, two devices can end up with different progress. Something has to decide which one survives, and that rule is what gets exploited. It gets its own section below.
Four structures you can use without a server
Detect rollback with a monotonic counter
Record a number alongside each save that increases by one every time you write. Then keep the highest value seen somewhere other than the save.
On load, if the save's number is lower than the recorded high-water mark, it was rolled back. You can at least tell that it happened.
An attacker who rolls back both locations still gets through, of course. This is not a prevention measure — it is a cost measure. What used to be copying one file becomes finding and handling two storage locations together.
Use time only to detect running backwards
Store the last observed timestamp, and if the next launch reads earlier than that, the clock moved back.
Moving forward is much harder to judge. Whether a day actually passed or the clock was pushed a day ahead, the device has no basis to tell them apart. A common mistake here is to punish as soon as a backward jump appears. Travel across time zones, daylight saving and automatic clock correction all move time legitimately.
Unless the game genuinely never touches the network, fetching a trustworthy timestamp occasionally is the surest answer. Confirming only the time, rather than standing up a full backend, is a much smaller lift.
Move reward design from time-based to progress-based
The most fundamental fix is not technical but a design one. Replace rewards that arrive because time passed with rewards that arrive because someone played, and clock manipulation has nothing left to win.
It does not fit every game. But it is worth knowing from the start that defending a time-based design without a server is inherently hard.
Bind the save to the device
Signing a device identifier alongside the save filters out lifting someone else's save file wholesale. It works against the pattern where "completed save files" circulate in a community.
Design the device-change and backup-restore paths at the same time. Without them, a legitimate player who switches phones loses their progress.
The cloud save trap — resolving conflicts is your job
This is the most commonly missed point in serverless games.
Google's Play Games Services saved games documentation is explicit about it. Conflicts arise when someone plays on several devices, when the service cannot be reached during a save, or when guest progress meets account progress. And the service does not resolve those conflicts for you. Your game decides which state survives.
The metadata offered for that decision is the ID, name, description, last modified time, played time and cover image. Which raises one problem from a security point of view.
Played time and description are supplied by the developer — that is, by the client. If your conflict rule is "keep whichever has the longer playtime", you have handed the choice to anyone who can edit that value.
Practical decisions to make:
- Decide the conflict rule explicitly. Leave it undecided and you still have one, arrived at by accident, and an attacker will use it.
- Do not decide on a single client-supplied value. Weigh several signals, or let the player choose.
- When the player chooses, show what they lose. The documentation likewise suggests telling players about guest-progress conflicts and letting them pick.
- Do not lose a legitimate player's data. This outranks everything else. Destroying real progress to stop manipulation is the worse outcome.
Confirm the exact APIs and current behaviour in each platform's official documentation — platform policy changes faster than this article does.
When a server stops being optional
Holding out without one is not indefinitely reasonable. If any of the following applies, the moment has arrived.
- There is ranking or competition, so one person's manipulation degrades someone else's experience.
- Currency obtained through in-app purchase affects game progression.
- There are player-to-player features — trading, gifting, guilds — where data moves between people.
- You have confirmed a manipulation case and have no way to tell how far it spread.
- You have no basis on which to answer a request to restore a legitimate player's progress.
Those last two decide it in practice. Without a server you cannot tell what happened, and cannot give anything back. That helplessness is harder on operations than the manipulation itself.
It does not have to be a full backend. A trustworthy timestamp, a record of save integrity, or collection of anomaly signals are all narrow places to start.
Checklist
Save structure
- The save carries a monotonically increasing number, with the high-water mark stored elsewhere.
- Save integrity is verified, and a device identifier is bound in.
- Device change and backup restore are part of the design.
Time
- Backward clock movement can be detected.
- Detection does not lead straight to punishment; legitimate causes are considered.
- If there are time-based rewards, there is a path to confirm a trustworthy timestamp.
Cloud saves
- The conflict resolution rule is explicitly decided.
- That rule does not rest on a single client-supplied value.
- A legitimate player's data survives a conflict.
Operations
- Records remain that let you check for signs of manipulation afterwards.
- The "when a server stops being optional" list above is revisited periodically.
What OZero Security covers, and what it does not
What we do not cover
- We are not a substitute for a server. We cannot change a structure where the client has the final say. Values that need server authority still need a server.
- Cloud save conflict rules, reward design and data recovery policy belong to your game design and operations.
What we do cover
- Judging whether the client reading and writing those saves has been tampered with. We identify executable binary tampering, debugger attachment and hooking, and untrusted runtime environments such as emulators and rooted devices, raising the cost of bypassing them.
- Detecting memory tampering and game speed manipulation at the native level through cross-verification. Speed manipulation is a standard way to attack time-based design.
- Save file and PlayerPrefs tamper protection, and device binding against copying a save from another device, with a reset callback you control for legitimate device changes. An optional web time check compares the device clock with public time sources to help detect clock manipulation.
- With the Pro Add-on, collecting telemetry from suspicious clients so you can act from the back office under your operational policy. For a team without a server, this is sometimes the first route to knowing what happened at all.
Putting verification in a Native C++ layer outside C# makes switching the verification itself off a separate piece of work — which is the "raise the cost" goal in a serverless setting.
In closing: design knowing you cannot prevent it
Protecting data in a serverless game is not about building a complete defence. That is structurally out of reach.
Approach it this way instead. Filter out casual manipulation, raise the cost of serious attacks, stay able to tell what happened, and stay able to restore legitimate players. That is the range available without a server.
And the moment you step past that range — ranking appears, purchased currency affects progression, or data starts moving between players — a server becomes a requirement rather than a choice. Knowing where that line sits makes the call much faster when you reach it.
Next steps
- Check the protection scope — platform support and what each plan (Standard / Pro) defends.
- Start a quick integration — the import and configuration steps are in the integration guide.
- Talk to us — ask what is achievable in a setup without a backend.