---
title: "Drift and reconciliation modes"
description: "What monedula-gitops counts as drift, how verify reports it, and how the reconciliation modes change what apply and the operator do."
url: https://monedula.dev/flock/docs/gitops/concepts/drift-and-reconciliation/
---
Drift is a difference between what your manifests declare and what the cluster has, for example a topic setting someone changed by hand. Each resource's reconciliation mode decides whether monedula-gitops corrects it or only reports it.

## What counts as drift

Live state is compared only with what your manifests declare, and only the kinds they declare are read ([CLI overview](/flock/docs/gitops/reference/cli/)):

- A topic, user or quota entity that no manifest names is not drift.
- Only the topic config keys in `spec.config` are compared. Live keys you do not list are never touched or reported.
- An ACL counts when it matches a principal and resource pattern that your manifests reference. An in-scope ACL that no manifest declares any more is a [prune candidate](/flock/docs/gitops/concepts/safety-gates/), and `verify` counts it as drift until it is pruned or declared again.
- `spec.limits` is authoritative for its quota entity, so a limit set live but missing from the manifest is drift.
- For a `KafkaUser`, the username, the declared mechanism and an explicitly set iteration count are compared, never the password ([Provision SCRAM users](/flock/docs/gitops/how-to/provision-scram-users/)).

A `KafkaTopic` can leave fields to another owner with `spec.drift.ignoreFields` (`partitions`, `replicationFactor` or `config.<key>`). `verify`, `diff` and `apply` all skip an ignored field; [Detect and fix drift](/flock/docs/gitops/how-to/detect-and-fix-drift/) has an example.

## How drift is reported

`verify` runs the same comparison as `diff`, names each drifted field and exits 1 on drift, which `diff` never does. Both accept `-o yaml` or `-o json`.

The operator checks for drift on every reconcile and on every [resync](/flock/docs/gitops/how-to/configure-the-operator/), so out-of-band changes are caught without a Git change. Drift appears in the resource status and in metrics such as `monedula_kafka_topic_drift_detected` (1 or 0 per resource).

## Reconciliation modes

`spec.reconciliation.mode` (on `KafkaTopic`, `KafkaAccessPolicy`, `KafkaQuota` and `KafkaRoleBinding`) works the same in both runtimes:

| Mode | `apply` | `verify` on drift | Operator |
| --- | --- | --- | --- |
| `Enforce` (default) | runs the operations | exits 1 | applies the diff |
| `DetectOnly` | reports the operations, never runs them | exits 1 | reports drift in status and metrics, on drift with the phase `Drifted` and `Ready=False`; never changes Kafka |
| `ObserveOnly` | reports the operations, never runs them, not even a create | shows the drift, exits 0 | reports drift in status and metrics and stays `Ready`; never changes Kafka |

Report-only operations never fail `apply`.

`Enforce` fits resources that your pipeline or operator owns. `DetectOnly` fits resources where drift should fail CI or raise an alert, but a person decides how to correct it. `ObserveOnly` never blocks CI, which suits auditing topics another team owns. Because an `ObserveOnly` manifest never creates anything, its topic must already exist.

## Related

- The [verify command reference](/flock/docs/gitops/reference/cli/verify/) lists its flags.
- The [KafkaTopic reference](/flock/docs/gitops/reference/resources/kafka-topic/) lists the `drift` and `reconciliation` fields.