> For the complete documentation index, see [llms.txt](https://docs.opendatadiscovery.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opendatadiscovery.org/developer-guides/architecture-decision-log/adr-0075-feature-gating-posture.md).

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

## 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

* [ADR-0004 — GenAI ships disabled by default](/developer-guides/architecture-decision-log/adr-0004-genai-disabled-by-default.md) — off-by-default instance.
* [ADR-0019 — Data Collaboration ships disabled by default](/developer-guides/architecture-decision-log/adr-0019-data-collaboration-disabled-by-default.md) — off-by-default instance.
* [ADR-0040 — Notifications ship disabled by default behind one condition](/developer-guides/architecture-decision-log/adr-0040-notifications-disabled-by-default.md) — off-by-default instance.
* [ADR-0046 — Housekeeping ships enabled by default (opt-out)](/developer-guides/architecture-decision-log/adr-0046-housekeeping-opt-out-by-default.md) — the deliberate on-by-default inversion.
