Back to Feed
article 3m read

Boundaries Make Small Changes Safer

A small change stays small when its inputs, authority, failure state, and rollback path are explicit.

Article DepthPractice

Flow

A practical boundary review

  1. 1Describe

    Name current authority, target, inputs, and owned fields.

  2. 2Observe

    Use dry-run, shadow, or advisory mode before influence.

  3. 3Effect

    Verify receipt, revision, scope, and external read-back.

  4. 4Recover

    Rollback only owned state under a current revision guard.

  5. 5Review

    Test malformed, stale, ambiguous, duplicate, and unknown outcomes.

Before implementing a small change, write a one-page boundary note. Name the current authority, the new path, the exact target, the input contract, the success evidence, the failure states, and the rollback owner. If the note cannot be written without phrases such as “the helper figures it out” or “we will know it worked,” the change is not yet bounded.

At the input edge, validate shape, scope, size, and freshness. Do not let a caller reconstruct a domain object from loosely related fields if the domain already has a canonical contract. Parse once at the edge and pass a typed value inward. Treat text from logs, files, providers, and users as data; it must not become instructions merely because it contains command-like words.

At the authority edge, distinguish authentication from permission and permission from target selection. A credential proves which service is calling. A role or policy grants a capability. A target and precondition identify what the capability may change. Keep those checks close to the mutation rather than assuming that an earlier screen or read-only check remains true.

At the effect edge, define the receipt. For a database write, it may be a committed revision and a read-back. For an external call, it may be a provider receipt or an authoritative read. For a file, it may be an atomic rename plus digest. A returned promise is not automatically an effect receipt. If a timeout leaves the outcome ambiguous, preserve unknown and reconcile before retrying when the effect could be duplicated.

At the recovery edge, define the owned fields and current revision. A rollback should not replace the entire record with an old snapshot because a different actor may have changed fields after the attempt. Apply a narrow inverse only if the current state still matches the attempt’s ownership and expected revision. If it does not, stop and ask for reconciliation.

Roll out in modes. A dry-run validates the plan without writing. Shadow produces a candidate result without changing authority. Advisory makes the result visible for review. Active mode should be a separate release decision, not the accidental result of changing a Boolean. Measure differences between old and new paths, but label sample outputs as illustrative unless they come from a defined test or production measurement.

Build the test matrix around the boundary. Include malformed input, missing scope, stale revision, ambiguous target, permission denial, provider timeout, provider rejection, partial response, database failure, read-back failure, duplicate request, and rollback after a later edit. Assert the durable state and the public output. A test that checks only a return value can miss a secret in logs or a mutation that happened before an error was raised.

Use the review checklist during code review: What can this change read? What can it write? What identity owns the write? What proves the effect? What remains unknown after a timeout? What prevents an old rollback from erasing a newer edit? Where can the feature be turned off? A few explicit answers are more valuable than a general statement that the change is small.

The final implementation should make the safe path ordinary. The read path stays read-only. The new behavior is bounded by a mode and a scope. The mutation revalidates. The result is recorded. The failure is visible. The rollback is narrow. Smallness then means not only fewer lines, but fewer unowned assumptions.

Keep reading

Pick up a connected idea or branch into a nearby one.

5 paths forward