Atomic Writes
When Vorliq saves JSON state, it writes a temporary file in the same directory, flushes it, fsyncs it, and then atomically replaces the target file. On Linux, the directory is fsynced when practical so the rename reaches disk safely.
Vorliq currently uses JSON-backed persistence for blockchain and application state. This page explains what is stored, how writes are protected, how corruption is detected, and how operators should respond to warnings.
The critical blockchain data files are chain.json, indexes.json, pending.json, peers.json, registry.json, lending.json, exchange.json, governance.json, treasury.json, price.json, forum.json, achievements.json, profiles.json, and faucet.json. These files affect balances, pending transactions, community records, public node state, and user-visible application state.
indexes.json is derived from chain.json. It can be rebuilt safely and is never the canonical source for historical blocks or transaction hashes. See Derived Indexes.
Backend JSON files such as analytics.json and incidents.json are also protected. Analytics is useful for product insight but is not required to reconstruct blockchain balances.
The current storage adapter is JSON. Future SQLite or PostgreSQL adapters must pass dry-run validation, preserve immutable block data, and remain rollback-safe before they can become active. See Storage Adapters, Storage Adapter Interface, PostgreSQL Adapter, and Schema Map.
When Vorliq saves JSON state, it writes a temporary file in the same directory, flushes it, fsyncs it, and then atomically replaces the target file. On Linux, the directory is fsynced when practical so the rename reaches disk safely.
Before a replacement, Vorliq keeps a .bak copy of the previous good file. Backup files are included in production backup archives where useful and are checked by the verification script.
Writes use lightweight lock files next to the JSON files, such as chain.json.lock. Lock attempts time out and log a clear error instead of waiting forever.
If the main JSON file is valid, Vorliq loads it. If it is corrupt but .bak is valid, Vorliq restores the backup and preserves the corrupt file with a timestamped .corrupt suffix. If both are invalid, the component receives a safe default and the error is reported.
chain.json is special. If it is corrupt and no valid backup exists, Vorliq does not silently replace it with a new genesis chain. The storage layer reports a critical health error and write-protects chain saving until an operator restores or repairs state intentionally.
Operators can rehearse a future database migration without writing a database or modifying production JSON:
python tools/migration_dry_run.py --output migration-dry-run-report.json
Do not commit real production dry-run reports. Use them as local operator evidence for counts, chain validation, missing optional files, and future table summaries.
The public endpoint GET /api/storage/health returns safe metadata only: file name, existence, JSON validity, backup availability, size, last modified timestamp, status, and a short message. It does not expose full server paths, secrets, private keys, or raw file contents.
The protected operator endpoint GET /api/admin/storage uses the same safety rules and requires the server-side admin token. The system self-check includes storage status, critical error count, and whether a backup is available.
/api/storage/health when storage warnings appear.deployment/verify_backup.sh against the newest archive before considering restore.deployment/restore_backup.sh ARCHIVE --dry-run first and review the output..corrupt.TIMESTAMP files for investigation; do not delete them until the recovery path is understood.