Modern games and apps love being data-driven. Items live in JSON. Enemies come from spreadsheets. Dialog is authored in YAML. At first, this feels safe: data isn’t code, right?
But here’s the uncomfortable truth:
The moment data starts deciding what happens, it’s behaving like code.
And that shift often happens without anyone explicitly choosing it!
The slippery slope
Most projects move along this path:
- Static data
player:
hp: 100
speed: 3.5
- Parameterized behavior Code defines logic, data tweaks the numbers.
- Rule-driven behavior Data starts choosing which logic runs and when.
That third step is where things get interesting — and risky!
A tiny example: data that behaves like logic
This looks harmless:
effects:
- type: "heal"
amount: 25
But once you add conditions…
effects:
- type: "if"
cond:
let:
- "player.hp"
- 30
then:
- type: "heal"
amount: 40
else:
- type: "heal"
amount: 10
…you’ve crossed a line.
This asset now contains:
- branching
- state inspection
- ordered execution
That’s not just data anymore. That’s a mini behavior script!
Why teams do this anyway
Because it’s powerful.
- Designers can iterate without engineers
- Balance changes don’t require code builds
- Live updates and hotfixes get easier
- Modding becomes possible
These are real wins. The problem isn’t doing it — it’s doing it by accident!
The hidden cost of “data as code”
Once assets control behavior, you inherit all the problems of code:
- Debugging: “Why did this trigger?”
- Validation: malformed data can crash logic
- Versioning: old assets break new runtimes
- Tooling: editors, schemas, tests become mandatory
If you don’t plan for this, complexity sneaks up fast!
A simple rule of thumb
If your data can:
- branch (if / else)
- reference runtime state
- apply ordered effects
- choose behaviors
Treat it like code!
That means:
- strict schemas
- clear error messages
- versioned formats
- limited, well-defined “instructions”
The takeaway
“Data-driven” doesn’t mean “safe by default.”
The moment your assets decide what happens next, you’re no longer just shipping data — you’re shipping behavior. And behavior deserves the same care, tooling, and respect as code.
If you design for that upfront, data-driven systems become a superpower instead of a slow-burn bug factory.