Ask about writers before asking about size
A small application does not necessarily have simple state. Two servers incrementing one counter can create a coordination problem involving just a few bytes. Reading thousands of fixed content records during a build may be easier. The first question is who changes the same state and in which order, not how many megabytes the file occupies.
The public JsonStore class in Inscribi Director reads a named JSON file. For a write, it creates a temporary file and renames it to the destination. It serializes large integer values as strings. This small interface keeps the bridge’s state logic separate from storage details, but its size says little about the consistency guarantees of the surrounding application.
What file replacement does not solve
A temporary file followed by a rename is used to reduce the risk of readers seeing a partially written destination. The inspected implementation does not contain a transaction across records, a multi-writer lock or an explicit disk-synchronization call. A single-file replacement should not be described as a guarantee that several files update together or that every completed write survives power loss.
The bridge also loads state into memory before changing it. If another process can update the same record, a complete JSON document does not prove that an update was based on current information. The last writer can overwrite another writer’s changes. Adding a second server consequently changes a storage assumption, not just a deployment setting.
Make the lost update visible
This example is neither application code nor a reported load test. It describes an ordering in which two workers read the same initial value. Each correctly adds one, but both started from the same snapshot. The final value contains only one increment. Valid JSON cannot detect that logical loss.
stored = {"count": 0}
worker_a = dict(stored)
worker_b = dict(stored)
worker_a["count"] += 1
worker_b["count"] += 1
stored = worker_a
stored = worker_b
assert stored["count"] == 1 # Two increments, one surviving update.Compare failure modes as well as convenience
This table supports an initial decision. Selecting a database does not write correct transactions for you; contention, retries and backup behavior still need design. SQLite’s documentation allows concurrent read transactions but only one simultaneous write transaction. An application must define how it handles that writing boundary rather than assuming it disappears.
| Option | Complexity | Scaling boundary | Typical failure mode |
|---|---|---|---|
| JSON with one writer | Low; file and schema management | One authoritative writer, small state | Stale memory, corrupt or missing file |
| Local SQLite | Moderate; schema and transactions | Coordinated access on one machine | Write contention, wrong transaction scope |
| Shared database service | Higher; connections and operations | Multiple application instances | Network loss, connection limits, races |
Write down the migration trigger
Revisit the file design when one user operation must change several records together, parallel background workers are added, or historical changes must be auditable. A concrete trigger is more useful than “we may grow later”: it allows infrastructure to stay small while identifying the moment when a change becomes necessary. A restore exercise belongs in the design from the beginning.
During migration, preserve the source files, validate their schema and compare imported record counts with the originals. Establish the moment when the new application becomes the writer so that old and new stores do not evolve independently. For a small application, the useful goal is not the fewest lines of code. It is a clear statement of what remains intact when an operation fails.
A recovery rehearsal should do more than open the file. Restart with a saved unresolved operation, inspect the restored state and observe whether a new external request is sent. This checks data preservation separately from correct workflow recovery. A controlled fake provider makes repeated effects observable without involving a live paid service.