Skip to content

Robust-code checklist

A review checklist for the failure modes that pass unit tests - happy path, single process, no concurrency, no injected failure - and only bite in production. These are general engineering principles, not CampusCore-specific conventions (those live in coding-principles.md). They're written down because "general" doesn't mean "automatically applied": an agent (or a person) reaching for the obvious happy-path implementation will miss most of them without a checkpoint.

When to run it

Before finalizing a change - and when reviewing or refactoring one - if it does any of:

  • runs on the request path (middleware, per-request hooks, anything on every request),
  • runs in a background job (worker, scheduled/EventBridge task, management command),
  • touches an external or cloud resource (S3, SQS, ACM/ELB, a connector API, an outbound fetch),
  • or changes infrastructure.

Not every item applies to every change - match by the trigger in brackets.

Failure handling

  • Request-path code fails open. [middleware / per-request hooks touching DB, cache, or an external service] Catch failure and fall back to a safe default; a dependency blip must not become a site-wide 500. Trap: a health probe short-circuited upstream can stay green while everything behind it fails, so "the probe passes" never means "the app works."
  • Every outbound call has a timeout and bounded retries. [any network call] No unbounded wait; decide the failure behavior explicitly. Never except: pass around primary behavior - catch only what you can handle.
  • Background jobs fail loud, not silent. [workers, scheduled tasks] Surface failure (retry budget, alert, mark failed) rather than swallow it - a job that swallows errors looks healthy while doing nothing. Handle each row/item independently so one failure doesn't abort the batch.

Concurrency & idempotency

  • Read-modify-write across a slow gap uses a conditional update. [a worker reads state → does slow work → writes back; or two writers on one row] Transition with a guarded UPDATE … WHERE <precondition-still-holds> that no-ops if the state moved; don't save the whole stale object over a concurrent write. (Optimistic concurrency.)
  • Retryable operations are idempotent. [queue- or schedule-triggered writes] Re-running must not duplicate or corrupt. Any dedup/idempotency key must be collision-free - hash it, never strip-and-truncate a string (distinct inputs collapsing to one key silently returns the wrong resource).

Consistency across boundaries

  • Order operations so a partial failure can't orphan state. [a local record mirrors an external resource - an S3 object, a cert, an external-API entity] Change/delete the external side first, confirm it, then the local record; on failure keep the record and retry. Dropping the local reference after a failed external call loses the handle and leaks the resource. Tolerate idempotent "already gone" as success.

Untrusted input & trust

  • Validate untrusted input at the boundary, and guard the whole operation, not just the input. [server-side fetch of a user/admin-supplied URL; parsing external data] For outbound fetches: disable redirect-following and pin the resolved IP - redirects and DNS rebinding reach internal targets (cloud-metadata endpoints, VPC hosts) the input check never saw. Normalize external data once at ingest (parse, don't re-validate downstream).
  • Verify identity, not just reachability or shape. [a trust or routing decision made from an external response] "It responded" / "it's well-formed" is not "it's the right, authorized thing." Check an identifier, signature, or ownership proof.

Invariants & observability

  • Enforce an invariant at the strongest layer that can guarantee it. [any rule the code depends on] A DB constraint beats app-side validation; a platform policy (e.g. an IAM Condition) beats app-code discipline. If code maintains an invariant a lower layer could enforce, one refactor can silently drop it - and a comment claiming a guarantee the layer doesn't actually enforce is worse than none.
  • Make security- or state-relevant changes observable. [changes to access, identity, trust, billing] Emit an audit signal (not just a debug log). And don't ship dead safeguards - a cache invalidation that no-ops across processes, a flag that changes nothing.

Change discipline

  • A fix or refactor gets the same scrutiny as new code. Re-derive the blast radius of every change, including "cosmetic" ones - a rename can cause a resource-name collision or break a public contract.