Skip to content

Business logic lives in the backend

State: open/published

  • Business logic and process state live in a backend. A frontend renders, holds view state and caches backend reads.
  • The test: if losing the state on reload, or not seeing it from a second client, would be a bug, it belongs in the backend.
  • The rule is language neutral. The backend may be Rust, TypeScript, or a plugin.

Business logic and process state live in a backend: core code today, a plugin later. A frontend renders, holds view state, and caches what the backend returns. It does not own domain rules or the state of a running process. The rule holds whatever language the backend is written in.

State that only a frontend holds is lost on reload and invisible to a second window, another client, an agent, or a CLI. Each frontend that needs the same rule writes it again, and the copies drift. Coordination bugs follow: a frontend that tracks several running processes has to guard every result against the one the user is looking at now.

A backend operation is also the only thing a plugin, an agent or another client can call. Logic kept in a frontend store cannot be reused by anything else.

  • Backend: domain rules, validation, decisions such as “this scan covered every check, so record its score”, process coordination (what is running, what it covers, how it ended), and anything that must survive a restart.
  • Frontend: view state (selection, highlight, scope, open panels, unsaved edit buffers), caches of backend reads, and derived values that only shape the display (sorting, grouping, counts for a view).
  • A running process is a backend job. The backend pushes its status; the frontend shows it and can reconnect to it after a reload. See D-0050.
  • A frontend may apply a change optimistically, but the backend’s answer is the truth.
  • When a frontend needs a rule the backend already has, it asks the backend. It does not mirror the rule.
  • Polish scan coordination is in the frontend today (solutions/determined/experiences/polish/app/stores/vaultScan.ts). It holds which scans run per vault, why a check failed, scan progress, and whether a scan was full. A reload loses all of it. The task Polish: scan coordination moves to the backend (T-YVKP) moves it.
  • Polish batches follow the rule. The batch journal, ignores and score journal are stored by the Rust backend, and the frontend loads them.
  • Where the backend code lives, and in what language, is decided elsewhere. P-0012-rust-core-adapters-as-needed covers Rust cores. A domain module that not every app needs is built so it can be left out, for example behind a build feature.
  • This does not ban frontend logic. Display logic stays in the frontend.
  • Existing frontend business logic is a defect to move when its area is next worked on, not a reason to stop work.

← Back to Principles