> 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-0046-housekeeping-opt-out-by-default.md).

# ADR-0046: Housekeeping ships enabled by default (opt-out)

## Status

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

## Context

The housekeeping subsystem (ADR-0045) deletes aged data: resolved alerts, search facets, and soft-deleted data entities past a TTL. Every other heavyweight subsystem in the platform — GenAI (ADR-0004), Data Collaboration (ADR-0019), Notifications (ADR-0040) — ships **disabled** by default, because each needs external configuration to do anything useful. Housekeeping is different in kind: it needs no external system, and the thing it prevents (unbounded table growth on an append-heavy platform) is a problem *every* deployment has. So the platform had to decide which default serves operators better — off (preserve everything, grow unbounded) or on (bound growth, delete aged data).

## Decision

**Housekeeping ships enabled by default — it is opt-out, not opt-in.** The shipped `application.yml` sets `housekeeping.enabled: true` verbatim, and `HousekeepingJobManager` is gated by `@ConditionalOnProperty(value = "housekeeping.enabled", havingValue = "true")`. A default deployment therefore runs the cleanup cycle and deletes aged data without any configuration; an operator who wants to keep everything must explicitly set `housekeeping.enabled: false`.

This is a **deliberate divergence** from the platform's ship-disabled-by-default family. Those features ship off because they are inert without external wiring; housekeeping ships on because **bounded database growth is the platform's default operational posture** — leaving it off would let the activity, alert, and search-facet tables grow without limit on every untouched deployment. The default encodes "the platform keeps itself bounded unless you tell it not to."

## Consequences

* 📌 **A default deployment deletes data.** Out of the box, resolved alerts, search facets, and soft-deleted data entities older than their TTL (each 30 days by default) are removed on the cleanup cycle. This is intended, but an operator who needs indefinite retention (for audit or compliance) must set `housekeeping.enabled: false` — and should know the default is *delete*, not *keep*.
* The TTLs are configurable (`housekeeping.ttl.*`), so retention windows can be lengthened rather than disabling the subsystem entirely.
* Because the condition uses `havingValue = "true"` with no `matchIfMissing`, the shipped-on default applies *through the shipped `application.yml`*: a deployment that replaces that file without re-supplying `housekeeping.enabled` gets housekeeping **off** (the absent key fails the condition). The integration-test profile relies on exactly this, setting `housekeeping.enabled: false` to keep test data. Operators templating their own config should carry the key forward deliberately.
* A contributor proposing to flip housekeeping to disabled-by-default "for consistency" with the other subsystems is working against this decision — the inconsistency is intentional and reflects that housekeeping is an operational-hygiene concern, not a feature integration.

## Evidence

* `odd-platform-api/src/main/resources/application.yml:165-166` — `housekeeping:` / `enabled: true` (the verbatim shipped default); `:167-170` — the `ttl` block (`resolved_alerts_days`, `search_facets_days`, `data_entity_delete_days`, each `30`).
* `odd-platform-api/.../housekeeping/HousekeepingJobManager.java:17-18` — `@Component` + `@ConditionalOnProperty(value = "housekeeping.enabled", havingValue = "true")` (no `matchIfMissing`): the strict gate that, combined with the shipped `true`, produces opt-out semantics.
* `odd-platform-api/src/test/resources/application-integration-test.yml:8-9` — `housekeeping:` / `enabled: false`: the test profile opts out, exercising the same toggle and confirming it is the real on/off switch.

## See also

* [ADR-0045 — Housekeeping is a separate subsystem from partition management](/developer-guides/architecture-decision-log/adr-0045-housekeeping-partition-separation.md) — what the housekeeping subsystem is and does.
* [ADR-0004](/developer-guides/architecture-decision-log/adr-0004-genai-disabled-by-default.md), [ADR-0019](/developer-guides/architecture-decision-log/adr-0019-data-collaboration-disabled-by-default.md), [ADR-0040](/developer-guides/architecture-decision-log/adr-0040-notifications-disabled-by-default.md) — the ship-disabled-by-default family this decision deliberately diverges from.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.opendatadiscovery.org/developer-guides/architecture-decision-log/adr-0046-housekeeping-opt-out-by-default.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
