Skip to content

Read-Only Mode

An operating mode — instantiates Safe Mode Operation

Allows viewing and retrieval while blocking every write and irreversible state change, so data integrity is protected when the system can't be trusted to change state safely.

Read-Only Mode is the safe-mode variant defined by a single, sharp rule: reads yes, writes no. It preserves all the functions that observe or retrieve state and blocks every function that changes it — no saves, no transactions, no deletions, no irreversible commits. Its distinguishing feature among the siblings is this clean line drawn on the mutation axis: it doesn't reason case-by-case about which features are risky, it simply treats any state change as the risk to be held off while the system is untrusted. That single rule is easy to reason about, easy to enforce, and exactly right when the danger is corruption or an irreversible action against data you can no longer vouch for.

Example

A wiki platform is migrating its database to new storage. During the cutover, the two copies could briefly diverge — a write landing on one but not the other would corrupt the record. Taking the site fully offline would block the thousands of people who just want to read articles. So the platform enters read-only mode. Every article stays fully viewable and searchable; the whole read path is untouched. But the "edit," "create," "upload," and "comment" actions are disabled, and any write that's attempted is cleanly refused with a clear message rather than silently dropped.

Readers barely notice — the encyclopedia is fully available to read. Editors see that saving is paused and are told when it'll return. Because no write can land during the window, the migration finishes with both copies guaranteed consistent, and edits resume the instant the cutover is verified. The one rule — block all mutation — is what makes the integrity guarantee absolute.

How it works

Read-only mode enforces one boundary: the read/write split. Every operation is classified as observing state (permitted) or mutating state (blocked), and the block is applied at a low, hard-to-bypass layer — a database flag, a connection set to read-only, an API gateway rejecting non-idempotent methods — so no path sneaks a write through. What distinguishes it from a hand-picked feature allowlist is that the allowlist here is definitional and total: reads are in, writes are out, with no per-feature judgment calls. The one design subtlety is handling attempted writes gracefully — refusing them visibly and safely, never accepting-then-losing them, so users know their change didn't take.

Tuning parameters

  • Write-attempt handling — hard-reject with a clear error, silently no-op, or queue-for-later. Rejection is safest and clearest; queuing preserves user intent but risks replaying stale writes when the mode lifts.
  • Read freshness — whether reads are served from live, replicated, or cached state, and whether they're stamped "as of." Looser freshness scales reads but can show users data that's behind.
  • Enforcement layer — application code, database, or gateway. Lower layers are harder to bypass but coarser; higher layers are more selective but easier for a stray path to evade.
  • Scope of "write" — whether logging, session updates, and analytics count as writes to block or as permitted side-channels, trading strictness against usability.

When it helps, and when it misleads

Its strength is a guarantee that's trivial to reason about: with all mutation blocked, no corruption or irreversible action can occur, while full read access keeps the system useful to everyone who only needs to look. It's the cleanest safe mode when the threat is to data integrity — during migrations, failovers, suspected corruption, or a compromised write path.

The classic failure mode is the silent dropped write: if attempted mutations are quietly discarded instead of visibly refused, users believe their change saved when it didn't, and the "safe" mode causes exactly the data loss it was meant to prevent — just relocated. A subtler trap is treating stale cached reads as harmless when users are actually making decisions on them. The discipline that guards against both is making refusal explicit and making read staleness visible: read-only is only safe if users can tell that their write didn't land and how current their view is.

How it implements the components

Read-Only Mode fills the block-all-mutation subset:

  • capability_limit — its core act: every write and irreversible state change is disabled.
  • essential_function_allowlist — the allowlist is definitional — all read and retrieval functions are permitted to continue, unrestricted.
  • restricted_mode_boundary — the boundary is the read/write line itself, drawn at a low enforcement layer so no path evades it.

It does not decide who is permitted to act (override_governance — see Privilege Scope Restriction) or govern how write capability is brought back in stages after the window (recovery_or_reentry_policy — see Staged Capability Restore); it defines the restriction by the read/write rule alone.

  • Instantiates: Safe Mode Operation — the variant defined by the single rule "reads yes, writes no."
  • Sibling mechanisms: Limited Service Mode · Maintenance Mode · Diagnostic Mode · Quarantine Mode · Feature-Flag Disablement · Manual Supervision Mode · Limp-Home Mode · Privilege Scope Restriction · Safe-Mode Banner or Indicator · Staged Capability Restore

Notes

Read-Only Mode and Limited Service Mode can look alike but differ in how the boundary is drawn: read-only uses one universal rule (no mutation), while limited service curates a per-feature allowlist of what stays on. Read-only is simpler and gives a cleaner integrity guarantee; limited service is more flexible when the safe subset doesn't align neatly with the read/write split.