> 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-0044-postgres-artefact-lazy-create-no-drop.md).

# ADR-0044: Postgres replication artefacts are lazy-created, never dropped

## Status

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

## Context

The notification WAL consumer (ADR-0043) needs two Postgres objects to exist: a logical **replication slot** and a **publication**. The platform has to ensure they exist before streaming — but it must also decide what to do with them over the platform's lifetime: create them automatically, and if so, ever remove them? Replication slots in particular are durable server-side objects that retain WAL on the primary until consumed, so their lifecycle has real operational weight.

## Decision

**The platform creates the replication slot and publication lazily on first leader run if they are absent, and never drops them.** When the elected consumer starts, it checks for each artefact and creates it only when missing: `SELECT EXISTS (... pg_replication_slots WHERE slot_name = ?)` then `createReplicationSlot()` if absent; `SELECT EXISTS (... pg_publication WHERE pubname = ?)` then `CREATE PUBLICATION ...` if absent. There is **no DROP path anywhere** in the notification subsystem — once created, the artefacts persist until an operator removes them.

This makes cleanup the operator's responsibility, by design. The decision keeps boot idempotent (restart, redeploy, or re-elect a leader without disturbing existing artefacts) and avoids the platform ever deleting an object an operator may have created, renamed, or be relying on. It is the same lazy-create-no-drop shape the platform uses for other Postgres-resident artefacts whose lifecycle outlives a single process (for example its range partitions).

## Consequences

* 📌 **Bounded growth requires operator action.** An unconsumed replication slot makes the Postgres primary retain WAL indefinitely, which can exhaust disk; because the platform never drops the slot, an operator who disables notifications (or renames the slot) must drop the old slot manually. The operator-facing notifications documentation states this cleanup responsibility.
* Boot is idempotent: the consumer can start, restart, or fail over without recreating or disturbing existing artefacts — the exists-check makes creation a no-op when they are already present.
* The platform never removes an operator's database objects, avoiding the risk of deleting something created or repurposed out-of-band — at the cost of the manual-cleanup burden above.
* Changing the configured slot or publication name produces a *new* artefact on next run and orphans the old one (it is not renamed or dropped) — another instance of the same operator-owns-cleanup consequence.

## Evidence

* `odd-platform-api/.../notification/NotificationSubscriber.java:104-126` — `registerReplicationSlot(...)`: `SELECT EXISTS (SELECT slot_name FROM pg_replication_slots WHERE slot_name = ?)`, and only on `false` does it call `createReplicationSlot().logical().withSlotName(...).withOutputPlugin("pgoutput").make()`.
* `odd-platform-api/.../notification/NotificationSubscriber.java:128-158` — `registerPublication(...)`: `SELECT EXISTS (SELECT oid FROM pg_publication WHERE pubname = ?)`, and only on `false` does it `execute("CREATE PUBLICATION %s FOR TABLE %s")`.
* No `DROP` statement (no `pg_drop_replication_slot`, no `DROP PUBLICATION`) exists anywhere in the `notification` package — confirmed by sweep — so neither artefact is ever removed by the platform.

## See also

* [ADR-0043 — The notification WAL consumer is a leader-elected singleton](/developer-guides/architecture-decision-log/adr-0043-notification-wal-single-leader.md) — the consumer that creates and relies on these artefacts.
* [Notifications](/features/active-platform-features/notifications.md) — the operator-facing guidance, including manual replication-slot cleanup.
