ScriptableObjects vs JSON vs SQLite in Unity - Which Data Layer to Ship (2026)

If you are building a Unity game in 2026, you will hear three answers whenever you ask where to put data. ScriptableObjects for designers. JSON for configs and saves. SQLite when things get serious. All three can be correct. The expensive mistake is picking one because a tutorial said it was best, then discovering six months later that your live-ops plan, modding goals, or save format needed something else.

This article is a shipping-focused comparison. It assumes you want a clear boundary between authoring data (what you build in the editor or pipeline), runtime state (what changes while the player plays), and persistence (what survives app restarts). You will see where each tool wins, where it fights you, and how teams usually combine them without turning the project into a science experiment.

If you want a deeper focus on ScriptableObjects as a design pattern first, read ScriptableObjects and data-driven design in Unity. For inventory-shaped problems specifically, How to build a modular inventory system in Unity without spaghetti code lines up well with the save boundaries below.

The real question is not which format, but which job

Before comparing engines of storage, split your data into three jobs.

Definitions describe things that exist as concepts. Weapons, enemy archetypes, dialogue lines, perk rules, and level metadata often live here. They change during development more than during a single play session.

Runtime state is what the current session cares about. Health, quest progress, unlocked flags, and procedural seeds usually live here. It mutates constantly.

Persistence is what you serialize so the player can leave and return. Sometimes that is a small blob. Sometimes it is a full snapshot of hundreds of rows.

ScriptableObjects, JSON, and SQLite each map onto those jobs differently. None of them magically solves all three without tradeoffs.

ScriptableObjects - the editor-native definition layer

ScriptableObjects are Unity assets. They load with the content pipeline, show up in the Inspector, support custom editors, and reference other assets in a way JSON files rarely match out of the box.

Strengths

  • Fast iteration for designers and programmers working inside Unity
  • Strong typing in C# and compile-time help when schemas evolve
  • Natural fit for shared definitions referenced by many prefabs
  • Works well with Addressables when you need downloadable content packs

Weaknesses

  • Not a friendly interchange format for external tools compared with JSON or SQL
  • Player-facing modding usually requires an export step or a parallel data path
  • Runtime patching of balance data often wants a text or remote layer anyway

Shipping takeaway
Treat ScriptableObjects as your in-editor source of truth for definitions when the team lives in Unity. They are not automatically your save format, and they are not always your live-ops delivery format.

JSON - the universal interchange format

JSON shines when humans and tools outside Unity need to read or write the same data. That includes mod kits, server-driven configs, localization tables exported from spreadsheets, and many save file strategies.

Strengths

  • Easy to generate from build pipelines and external editors
  • Simple to version and diff in source control when files stay small
  • Works across platforms with minimal dependencies if you control size and parsing
  • Natural fit for REST APIs if you later add online features

Weaknesses

  • Large saves can get slow without streaming or chunking strategies
  • Schema drift is easy unless you enforce versioning and migrations
  • Referential integrity is manual. Nothing stops you from typos in ids

Shipping takeaway
JSON is ideal when interoperability matters as much as runtime performance. Many shipped Unity games keep ScriptableObjects for authored content, then export a player-facing or runtime subset to JSON during build or at boot.

SQLite - structured storage when relationships matter

SQLite gives you tables, indexes, queries, and transactions on device. It is attractive when you have large inventories, quest journals with many relations, analytics buffers, or tooling that already speaks SQL.

Strengths

  • Efficient reads and writes for large structured datasets
  • Easier partial updates than rewriting a giant JSON document
  • Familiar patterns for anyone who has built backends or tools in SQL

Weaknesses

  • Heavier integration story than JsonUtility or Newtonsoft for small projects
  • You must think about threading, file locks, and corruption recovery
  • Overkill if your save is a few hundred keys

Shipping takeaway
SQLite earns its place when queryability and scale beat the simplicity of a single JSON file. If your save is basically a struct with twenty fields, SQLite is probably not your first milestone.

A practical decision matrix

Use this as a blunt instrument, not a law.

Need Lean toward
Designer-tuned stats in Unity ScriptableObjects
Mod-friendly or external authoring JSON (often exported from SOs)
Small save, simple schema JSON or a binary serializer you control
Huge inventories, relational quests SQLite
Live balance without app update Remote JSON or server + local cache
Strict offline-first MMO-style journals SQLite + explicit migrations

Most mid-size Unity games end up hybrid. ScriptableObjects for authored definitions, JSON or binary for saves, and occasionally SQLite when the feature set outgrows flat files.

Hybrid patterns that survive production

Stable ids everywhere
Whether you choose JSON or SQLite, store references as stable string or int ids. Do not serialize Unity object references directly into portable layers.

One migration layer
When you change schema, bump a saveVersion integer and run a small migration path. That is true for JSON and SQL alike.

Separate tuning from story state
Balance values should not be the same blob as spoiler-heavy quest state if you can help it. It makes debugging, cheating policy, and customer support easier.

Test save upgrade on old files
Keep one save from every public build. Load it in the next build before you ship. This catches silent corruption more reliably than unit tests alone.

Common mistakes to avoid

Using ScriptableObjects as the only save system
You can serialize them, but you will fight references, asset bundles, and platform constraints. Prefer a dedicated persistence model.

One giant JSON save
It works until it does not. The failure mode is slow writes, memory spikes, and merge conflicts when you add fields.

SQLite without a backup strategy
Mobile OS updates, sudden kills, and cloud sync can corrupt files. Keep atomic writes and a fallback slot.

Changing field names without migrations
Renaming JSON keys or SQL columns without a migration path breaks returning players. Treat schema like API compatibility.

FAQ

Should solo devs default to ScriptableObjects plus JSON saves?
Often yes. It keeps authoring pleasant and keeps persistence simple until data volume forces SQLite.

Is Newtonsoft JSON worth it over JsonUtility?
If you need dictionaries, polymorphic lists, or clearer null handling, many teams adopt Newtonsoft or System.Text.Json on modern runtimes. Pick one and standardize.

Can I ship mods if I use ScriptableObjects only?
You usually expose a JSON or folder-based mod format at runtime, or ship a conversion tool. Players rarely edit .asset files directly.

When does SQLite become faster than JSON in practice?
When you routinely update small parts of a large dataset, or when you need indexed lookups over thousands of rows.

Does this replace a full backend?
No. Local SQLite and JSON solve on-device persistence. Online games still need server authority for anything competitive or economic.

Conclusion

ScriptableObjects, JSON, and SQLite are not three competitors where only one may live. They are three layers that solve different constraints. ScriptableObjects optimize Unity-native authoring. JSON optimizes interchange and many save strategies. SQLite optimizes structured scale on device.

Pick the smallest combination that fits your next milestone, keep ids stable, and invest early in versioning. If you do that, you can evolve from a weekend JSON save to a SQLite-backed live game without rewriting your entire design pipeline.

If this helped you untangle your stack, bookmark it for your next project kickoff or share it with a teammate who is still storing everything on a single mega prefab.