Every familiar tool trades clean code for runtime cost
Each option is good at something — and each breaks on either maintainability or the frame budget. That dilemma is the real problem.
ScriptableObjects & manager singletons
Fine for config and small state. As soon as data must be queried, joined and kept consistent, they become a database with no schema, no indexes and no query planner — maintained entirely in your head.
Manual dictionaries + hand-rolled indexes
They work until a second index has to stay in sync with the first. Then every write path must remember to update every derived structure, and the ones it forgets become your bugs.
An event bus for "refresh on change"
It starts clean and becomes its own spaghetti: refresh order is implicit, over-refreshing burns the frame, under-refreshing ships stale UI, and nobody can safely add a dependency.
Just embed SQLite or an ORM
Now you pay it all at runtime: query parsing, planning, reflection, allocations and millisecond latency — none of which fit IL2CPP or a per-frame budget measured in microseconds.
You already know every query before you ship.
Your game ships with a fixed set of screens. The shop runs the same offer query it ran yesterday; the inventory the same lookup. You know the whole catalogue of questions your game will ever ask before the build leaves your machine — so there's no reason to work them out again on the player's device, every frame.
ConjureDB keeps the one good idea — describe data declaratively, in one place — and moves the entire cost from runtime to build time. The compiler does once, correctly, what you'd otherwise do by hand, every frame, slightly wrong.
Four wins from one decision
Features that travel between games
Behind a declarative schema, a feature owns its data on its own terms — not welded into one game's managers and presenters. Build a shop or inventory once and carry it into the next project.
Fast without hand-optimizing
A cost-based optimizer turns the lists you'd loop over into index lookups, and picks the plan for you. You stop hand-tuning data code and the frame budget stops being the thing you fight.
Screens that refresh themselves
Incremental view maintenance keeps a view current by applying only what changed — no manual OnChanged wiring, no refresh-order bugs, no stale UI. Shapes it can't maintain are rejected at compile time, not silently degraded.
It stays manageable as it grows
One home for data logic instead of a tangle across scripts. The coupling that makes a growing game unmaintainable goes away — so the project stays workable from 3 systems to 30.
When not to use ConjureDB
A tool you can trust draws its own boundaries out loud. ConjureDB's strengths come from its constraints — here is where it is the wrong choice.
Arbitrary runtime queries
If designers must type new queries that run on player devices, you need a runtime engine. ConjureDB is closed-world: queries are known and compiled before ship.
Trivially small or throwaway state
Three booleans behind an options menu, or a prototype you delete in two weeks, do not need a schema. A dictionary is the right answer.
A multi-writer server database
This is single-writer and client-owned — no MVCC, no row locks, no distributed transactions. It is a fast local layer, not a contention-solving backend.
A source of authority
It is a fast local cache, not a security oracle. Premium currency and competitive rankings still need server truth.
The cost is real, too: a schema to maintain, a build step, and a new way of thinking for your team. We think it is worth it for a growing game that wants to keep both its architecture and its frame budget — but you should decide with eyes open.
See the mechanism, not a pitch
ConjureDB earns trust by opening the box. Read how the compiler works — and how you can read the C# it generates.