ADR-0075: Heavyweight features ship off by default; operational-hygiene jobs ship on

Outbound features (GenAI, Data Collaboration, Notifications) ship disabled and need explicit wiring; housekeeping and other hygiene jobs ship enabled, keeping the database bounded.

Status

Accepted. Reconstructed from the codebase on 2026-05-31; the decision is live in the source today.

Context

The platform keeps gaining optional capabilities. Some reach outside it or add real weight — an LLM proxy, Slack collaboration, alert notifications — and each needs external wiring (an API key, an OAuth token, a webhook) plus the cost, latency, and security surface that comes with it. Others are internal and keep the platform healthy — housekeeping jobs that purge resolved alerts, expired search sessions, and soft-deleted entities so the database does not grow without bound. A platform with many feature flags needs a consistent rule for what is on out of the box and what is off, rather than deciding each flag's default ad hoc.

Decision

Two opposite defaults, chosen by one rule. Features that reach outside the platform or add significant weight ship off — the operator must explicitly enable and wire them. Operational-hygiene jobs that keep the platform bounded ship on — the operator must explicitly opt out.

  • Off by default: GenAI (ADR-0004), Data Collaboration (ADR-0019), Notifications (ADR-0040) — all default to enabled: false.

  • On by default: Housekeeping (ADR-0046) — defaults to enabled: true, the deliberate inversion of the off-by-default family.

The rule behind the split: an operator should never be surprised by outbound traffic or a third-party dependency they did not ask for — so those are opt-in; but an operator should also never have to opt in just to stop their own database from growing forever — so hygiene is opt-out. The dangerous-to-assume direction differs by feature type, and the default is set against the danger in each case.

Consequences

  • A fresh install is inert and self-contained on the outbound axis: no LLM calls, no Slack, no notifications until configured. Nothing phones home, and the platform boots without any third-party service present.

  • A fresh install stays bounded without action: housekeeping runs by default, enforcing the retention TTLs. An operator who wants to retain everything has to opt out deliberately (ADR-0046).

  • The asymmetry is intentional and worth recording precisely because it is a default-safety judgment, not an oversight: silently enabling an outbound feature is the hazard on one side, silently disabling hygiene (unbounded growth, and eventually a full disk) is the hazard on the other.

  • A contributor adding a capability inherits the rule: an outbound or heavyweight feature ships off behind a condition; a bounded-growth hygiene job ships on with an opt-out. The housekeeping retention windows carry their own caveats — see the housekeeping records for the TTL details.

Evidence

  • odd-platform-api/src/main/resources/application.yml:17-18 (genai.enabled: false), :200-205 (datacollaboration.enabled: false), :172-173 (notifications.enabled: false) — the off-by-default outbound/heavyweight features.

  • odd-platform-api/src/main/resources/application.yml:165-166 (housekeeping.enabled: true) — the on-by-default operational-hygiene inversion.

  • The per-feature gating mechanism and rationale live in the instance records: ADR-0004 (GenAI), ADR-0019 (Data Collaboration), ADR-0040 (Notifications), ADR-0046 (Housekeeping opt-out).

See also

Last updated