Back to blog

Config drift that nobody owns: Why production quietly stops matching what you think you run

Row of black server racks with dense red and blue cabling in a brightly lit data center aisle.

Somewhere in your estate sits a setting that was never meant to be permanent. A console click during an incident. An env var pasted to unblock a deploy. A "temporary" resource limit raised for one customer and never walked back. Months later production still runs on that exception, while your declared config, your last merge, and your mental model all disagree. That is how config drift becomes an unowned production surface.

Mid-size teams rarely fail because they change settings. They fail because intended state has no owner, console and hotfix paths quietly outrank the declared path, and "we will clean it up after the release" never becomes someone's job. This post is about treating live configuration as change you operate, not as side effects you hope the next deploy will overwrite.

Settings that outlive the hotfix

A production value that no longer matches what your team believes is deployed is not minor housekeeping. It is an unmanaged fork between intent and reality. The original change was often reasonable. Raise a timeout during a vendor blip. Flip a cache size for a launch weekend. Patch a feature toggle in the admin UI while the PR waits. Months later those same values sit in cloud consoles, secret stores, and local overrides as if they were the designed system.

In practice, mismatch is the tell. If a setting has no named owner, no declared source of truth, and no record of who last changed it on purpose, it has stopped being configuration. It has become tribal memory with write access. Teams discover that only when a redeploy "fixes" something that was never broken in code, or when a new region boots from declared config and behaves unlike the cluster everyone trusted.

That's why inventing another CMDB rarely helps. More places to document intended state still leave you with live state nobody reconciles. Ownership of drift beats a prettier inventory of values nobody dares to touch.

Why live config quietly becomes the real system

Teams leave drift alone for reasons that sound careful. Reverting a console change might break a path nobody fully mapped. The hotfix still protects one noisy customer. The IaC PR never caught up after the incident. The person who knew which overrides were load-bearing left, and the ticket to reconcile keeps slipping behind features.

However, the social drift is sharper than the technical one. When engineers learn that console clicks survive forever, they stop treating declared config as authoritative. When managers learn that reconcile work always gets postponed, they stop funding the inventory. Culture follows the path of least rollback. Unowned drift trains everyone to treat production as a snowflake that must not be disturbed.

Still, you can name the usual leftovers without a forensic novel. Hotfix resource limits left high after the spike, env vars edited in the runtime and never committed, cloud security group exceptions for a one-time integration, and "temporary" feature settings that became silent product variants. If those leftovers have no owner and no reconcile clock, they are not pragmatism. They are permanent architecture wearing an emergency badge.

Who owns intended state when production disagrees

Someone has to own the config lifecycle. Not "platform in general," and not "whoever last opened the cloud console." A named owner decides which systems may hold standing live config, who may change production outside a declared path, how exceptions are recorded, when reconcile is mandatory, and what happens when the human who clicked has left the company.

In reality, mid-size org charts often leave that ownership floating. Product wants the exception for one customer. Engineering wants a fast unblock. Security wants least privilege restored. Nobody wants to be the person who reverts a quiet override and discovers it was load-bearing at 02:00.

Write the contract in operational language. Name the systems that may hold standing live config, the roles allowed to change production outside declared paths, the inventory where purpose and owners are listed, the default maximum age for exceptions, the evidence required after reconcile, and who can accept a dated exception when live and declared still disagree. If that list is empty, you do not have a configuration practice. You have folklore plus hope.

Meanwhile, pair ownership with authority that matches the change. An engineer told to "clean up drift" without permission to revert console values, update support scripts, or refuse a new permanent exception is not safer. They are a human holding a diff without a mandate. Ownership includes the decisions the role may make and the escalation when a temporary setting turns out to be load-bearing product.

Evidence that intended state still wins

A green "IaC configured" checkbox is not evidence that production still matches intent. Evidence is specific. It includes a current inventory of live exceptions, named owners, known consumers, recent successful reconciles, and a record of what broke and got fixed when age limits were enforced. Prefer a short drift log a tired engineer can trust over a policy page that only proves you can click Apply.

Finally, treat "temporary" as a timed contract, not a label on a setting that never expires. Temporary should mean a start, a planned reconcile or decision date, a reason, and a human accountable for closing or renewing it on purpose. It should not mean "until someone notices." If your tooling cannot show which standing exceptions exist, who owns them, where they diverge, and when they last had a reconcile decision, you do not have config management. You have durable snowflakes with better storytelling.

Yet keep the bar humane. You do not need perfect declared state for every corner path on day one. You need proof the common production paths have owners, declared sources, and a practiced reconcile. Settings that cannot meet that bar should be cleaned up, time-boxed with an owner, or promoted into explicit declared configuration on purpose. Leaving them untouched trains the team to mint the next permanent exception the first time an incident gets loud.

A reconcile habit mid-size teams can keep

You do not need zero exceptions tomorrow. You need a repeatable habit that stops live config from becoming anonymous architecture.

In practice, a workable pattern looks like this.

  • Inventory live exceptions that still diverge from declared config on production paths, and require a named owner, a purpose, known consumers, and a reconcile or decision date for each one in plain language.
  • Prefer declared paths with default expiry for emergency overrides, and document every intentional long-lived exception with the same ownership bar as a production service.
  • Record where each drifted value is consumed, including runtimes, admin tools, support playbooks, and dependent jobs, so cleanup is a checklist instead of an archaeological dig.
  • Reconcile on a cadence you can survive, starting with the oldest orphaned exceptions and the ones tied to finished incidents, and treat failed consumers as backlog, not a reason to stop.
  • Rehearse a reconcile for one critical path before the forced cleanup, including compare, revert or promote, and verify, so the first real cleanup is not a discovery exercise.
  • After every messy incident or departure, ask which settings that person still owns or that still depend on their undocumented clicks, assign owners, and refuse to call the change done while orphaned drift remains without a dated plan.

Instead of minting another forever override after a tense night, mint a time-bounded exception, a consumer list, and a reconcile owner. Exception volume is easy to grow. Making production match intent again is the scarce discipline.

When quiet drift becomes expensive

Long-lived config drift feels cheap until the first confusing failover, the support ticket that depends on a forgotten override, or the audit that asks which production values still match what you claim to run. Then you pay in unreproducible environments, slow incident response, and a culture that cannot tell intentional configuration from archaeological leftovers. Mid-size teams feel it faster because the same few people own the console, the pipeline, and the apology.

In the end, treat standing live config as a product surface for operators and product together. Name who owns intended state, bound exception age, keep consumer evidence, and practice reconcile before the next departure and before the next incident forces your hand. Ask the uncomfortable question while the next console click is still optional.

If every emergency override older than ninety days disappeared tomorrow morning, would you know which paths still need them, who owns the single remaining value, and how to bring production back to declared state without inventing the map under pressure, or would those settings prove they had already become the real system?

TL;DR

  • Config drift that outlives the hotfix quietly becomes permanent architecture, even when the wiki still describes declared state as truth.
  • Longevity without owners, consumers, and reconcile clocks is unowned production surface, not pragmatism.
  • Name an owner for intended state, including who may change production outside declared paths, how exceptions are recorded, default age limits, and exception review.
  • Treat temporary overrides as timed contracts with start, planned reconcile or decision, reason, and accountable renewal, not as labels on forever snowflakes.
  • Keep a simple reconcile habit: inventory, prefer declared paths where possible, map consumers, clean orphans first, rehearse, and clean up after incidents and departures.
  • Ask whether tomorrow's forced cleanup would be a controlled reconcile, or proof that forgotten overrides already hold up production.