Infrastructure as Code and GitOps Questions
Defining and managing infrastructure and delivery state declaratively: provisioning as code (Terraform, CloudFormation, Pulumi, Ansible, Puppet), configuration management, idempotency, drift detection and remediation, and version control for infrastructure definitions, extended by GitOps where git is the source of truth for deployment and infrastructure state. Covers keeping environments consistent, treating config as a first-class versioned artifact, pull-based deployment and continuous reconciliation toward the committed state (ArgoCD, Flux, and similar controllers), Kubernetes manifest and configuration delivery via git, secrets handling for IaC and GitOps pipelines, policy-as-code guardrails (OPA, Sentinel), Terraform state management and locking, and auditable change through version control: branching strategy, pull request review, commit conventions, and code review policy for infrastructure code. Distinct from the CI/CD pipeline design topic, which owns generic pipeline structure and platform-scale release orchestration (build, test, artifact publishing, runner mechanics) and the architectural choice between push-based CI/CD and pull-based GitOps, even when the payload is infrastructure code. Distinct from the safe deployment and rollback strategies topic, which owns deployment-strategy mechanics: canary and blue-green traffic shifting, automated rollback triggered by metrics or SLOs, feature-flag progressive delivery, Kubernetes rollout mechanics (maxSurge, maxUnavailable, health-check gating), and database or schema migration safety as it gates a release, even when the delivery mechanism is GitOps. Distinct from the automation and scripting topic, which owns operational-scripting disciplines (retry and backoff logic, CLI tool design, generic file, checksum, or diff utilities) when the task is not specifically about declarative infrastructure or configuration state. This topic keeps the GitOps reconciliation loop itself, drift detection and remediation, and IaC state and module lifecycle management regardless of which adjacent discipline a question also touches.
Design a scalable GitOps pipeline for managing infrastructure across multiple cloud accounts and clusters supporting dev/staging/prod. Requirements:
- Declarative manifests live in Git
- Automated reconciliation with drift detection
- Role-based access controls per environment
- Approval gates for production
- Secure handling of secrets
Describe repository layout, automation components (controllers, CI), workflows for PRs and merges, and rollback procedures for failed reconciliations.
Sample Answer
Direct answer
A scalable, multi-account, multi-cluster GitOps pipeline needs its ROLLBACK PROCEDURE for a FAILED reconciliation to be a first-class design element, not an afterthought, because at this scale a partial reconciliation failure (some manifests applied, others rejected mid-sync) is a routine operational event, not an edge case. The design combines a repo layout mirroring the account/cluster/environment hierarchy, a controller instance per cluster (never one controller reaching across account boundaries, which would undermine the RBAC isolation the requirements explicitly call for), and an explicit, tested procedure for what happens when a sync fails PARTWAY, distinct from ordinary drift-correction rollback.
Structured elaboration
Repository layout. A structure mirroring the real topology: clusters/<cloud-account>/<cluster-name>/<environment>/, with shared platform manifests factored into a common base that each cluster-environment combination overlays. This makes "which cluster does this manifest actually apply to" answerable by directory path alone, essential once the fleet spans enough accounts and clusters that tribal knowledge stops scaling.
Automated reconciliation with drift detection. One controller instance PER CLUSTER (not one central instance spanning every account), each watching only its own directory in the shared repo, so a compromise or misconfiguration in one cluster's controller cannot reach across the account boundary to another.
Role-based access controls per environment. Each environment's controller service account holds Kubernetes RBAC scoped to exactly that cluster; human access to trigger manual syncs or view status is scoped via the GitOps tool's own project/tenancy construct, matching the SAME account/cluster/environment boundaries the repo layout encodes, so the repo structure, the RBAC structure, and the controller topology all reflect the SAME hierarchy rather than three independently-maintained mappings that can drift out of sync with each other.
Approval gates for production. A required-review gate on any PR touching a prod environment directory, structurally enforced via CODEOWNERS and branch protection, distinct from and in addition to non-production environments' lighter review bar.
Secure handling of secrets. Per-cluster External Secrets Operator instances, each scoped to that cluster's own path prefix in the secrets backend, so a promotion between environments never requires touching a secret VALUE directly, only the reference structure.
Rollback procedures for failed reconciliations, the part this question specifically emphasizes. Distinguish two failure shapes: (1) a sync REJECTED entirely before applying anything (a validation or policy-as-code failure catches it up front), which needs no rollback at all, nothing was ever applied; and (2) a sync that applied SOME resources before failing partway (a dependency ordering issue, a transient API error on one specific resource), which leaves the cluster in a genuinely INCONSISTENT intermediate state, some resources reflecting the new desired state, others still on the old one. For case 2, the controller's own automatic retry (most GitOps controllers retry a failed sync automatically on the next reconciliation cycle) is usually sufficient IF the underlying cause was transient; if it is not transient (a genuine configuration error), the safe procedure is reverting the OFFENDING commit specifically (not the whole recent history) and letting reconciliation catch the cluster back up to the last known-good state, the same Git-revert-and-reconcile pattern used for ordinary rollback, but explicitly TESTED against a partial-failure scenario before relying on it in production, since a partial failure's exact intermediate state is harder to reason about than a clean, fully-applied-then-reverted change.
Worked example
A concrete PR/merge workflow tying the pieces together: a change merges into clusters/account-b/cluster-3/prod/, requiring @org/platform-team approval (CODEOWNERS) before merge is even possible; on merge, cluster-3's dedicated controller instance (holding RBAC scoped only to that cluster) picks up the change and begins syncing; if the sync fails after applying 6 of 9 manifests (a dependency ordering problem causes the 7th to fail), the controller's automatic retry attempts the remaining 3 on the next cycle; if the underlying issue is NOT transient (a genuine error in the 7th manifest), an operator reverts specifically that commit, and reconciliation, on its next cycle, reconciles the cluster back to matching the reverted (last known-good) declared state, resolving the partial-application inconsistency without requiring a manual, resource-by-resource cleanup.
Trade-offs and pitfalls
- Common mistake: designing rollback procedures only around "a bad change reached prod and needs reverting" and never explicitly testing the PARTIAL-failure case, a sync that applies 6 of 9 manifests before failing leaves a genuinely different, harder-to-reason-about intermediate state than a clean, fully-applied bad change; if this specific case has never been deliberately exercised (a game-day exercise, or a staging-environment fault injection), the team's confidence in "we can just revert and reconcile" may not survive contact with a real partial failure.
- One controller instance per cluster, rather than one centralized instance across accounts, is the right default here specifically because the requirements name per-tenant RBAC and account isolation explicitly; a centralized controller would need its OWN cross-account credentials to reach every cluster, which is exactly the concentration-of-risk a single shared credential creates for isolation-sensitive requirements.
- The repo-layout, RBAC-structure, and controller-topology hierarchies all mirroring the SAME account/cluster/environment structure is a deliberate design choice, not a coincidence, letting any one of the three drift out of alignment with the others (a repo reorganization that doesn't get reflected in RBAC scoping, for instance) reintroduces exactly the kind of tribal-knowledge dependency this design exists to eliminate at scale.
- Automatic retry on transient failures is genuinely helpful but can mask a persistent problem if not paired with alerting on REPEATED failures for the same resource, a sync that keeps failing and retrying silently, cycle after cycle, without ever escalating to a human, is a worse outcome than a sync that fails once, loudly, and gets a deliberate revert.
Design a phased migration plan to move from manual SSH-based config changes to a fully automated GitOps model for a 200-server mixed environment. Include discovery, pilot, incremental enforcement, rollback plan, training, and metrics that demonstrate progress and safety.
Sample Answer
Direct answer
A 200-server, SSH-based-to-GitOps migration needs a phase order where each phase produces the EVIDENCE the next phase needs to proceed safely: discovery captures what each host actually runs (not what documentation claims), a pilot proves the automated pipeline itself works end to end on a small, representative slice before it touches the fleet broadly, incremental enforcement expands cohort by cohort with an explicit rollback plan attached to each cohort (not just to the project as a whole), and training runs IN PARALLEL with the technical rollout, not after it, since engineers still doing SSH-based manual fixes on hosts already under GitOps management is itself a source of the exact drift the migration is trying to eliminate.
Structured elaboration
Discovery. An agentless scan (or targeted SSH-based fact-gathering, since these hosts are, by the question's own premise, currently managed via SSH and likely lack any config-management agent yet) inventories installed packages, running services, and key configuration files across all 200 hosts, without changing anything; this becomes the seed for the first-generation desired-state declaration per host, generated FROM observed reality rather than hand-authored from potentially stale runbooks.
Pilot. A small (10 to 15 host), genuinely REPRESENTATIVE slice, not just the easiest hosts, chosen to exercise the pipeline's real edge cases early: at least one host from each major service category present in the fleet, so a category-specific problem (a service with an unusual startup dependency, for instance) surfaces during the pilot rather than during the broader rollout. The pilot's goal is validating the WHOLE pipeline (discovery-to-declaration, GitOps controller reconciling correctly, alerting working, rollback tested for real) end to end, not just "did the config apply without erroring."
Incremental enforcement. Expand in risk-ordered cohorts: each cohort goes through discover, audit-only (dry-run, human-reviewed), then enforce, and only proceeds to the NEXT cohort once the current one has run cleanly under enforcement for a defined bake period. For 200 hosts specifically, a workable cadence is 3 to 5 cohorts of increasing size and risk over roughly 8 to 12 weeks, front-loaded with the pilot's already-proven pipeline reducing the risk of each subsequent cohort relative to a from-scratch rollout.
Rollback plan. Two distinct rollback levels, not one: PER-COHORT rollback (if a specific cohort's enforcement causes problems, revert JUST that cohort back to manual/audit-only status while leaving already-successful cohorts under enforcement) and PIPELINE-LEVEL rollback (if the automation itself is found to be fundamentally broken in some way discovery did not catch, pause new-cohort enrollment fleet-wide while the pipeline issue is fixed, without necessarily un-enforcing already-successful cohorts, since their success is independent evidence the CONFIGURATION is right even if a newly-discovered pipeline bug affects a DIFFERENT case).
Training. Running in parallel with the technical rollout, not sequenced after it: engineers whose hosts have moved to "enforce" status need to understand, before that cutover, that SSH-based manual fixes on THOSE hosts will now be automatically reverted (the auto-heal behavior), and what the new correct path is (a Git commit and PR, not an SSH session) for making a legitimate change; training delivered only after enforcement is live risks exactly the friction of an engineer's habitual manual fix being silently reverted, which damages trust in the whole migration if it is the engineer's first encounter with the new model.
Metrics demonstrating progress and safety. Percentage of the 200-host fleet under active enforcement (a simple, visible progress metric); MEAN TIME BETWEEN unauthorized-drift EVENTS on already-enforced hosts (should trend toward "rare," and any occurrence should be investigated, not just auto-reverted and ignored); count of manual SSH sessions to enforced hosts over time (should trend toward zero, since a legitimate need to SSH into an enforced host for anything beyond read-only debugging signals either a gap in what the declared state covers or a training gap); and INCIDENT rate correlated with migration cohort (confirming enforcement is not, in practice, causing more incidents than it prevents, the actual safety claim the whole migration rests on).
Trade-offs and pitfalls
- Common mistake: choosing the pilot cohort purely by "which hosts are easiest," rather than by which hosts best represent the fleet's real diversity. An easy-only pilot can complete successfully while leaving a whole category of real complexity (a particular service's unusual dependency, a particular team's non-standard setup) completely untested until it surfaces mid-rollout in a larger, higher-stakes cohort.
- Training delivered only after enforcement goes live, rather than in parallel with the technical rollout, is the single most common way a technically successful migration still damages team trust. An engineer's first experience of the new model should not be "my emergency fix silently vanished and I didn't know why"; that specific bad first experience, even if quickly explained afterward, tends to produce lasting resistance to the migration.
- The two-level rollback distinction (per-cohort versus pipeline-level) matters because conflating them either overreacts (un-enforcing successful cohorts because of a bug that only affects a different, not-yet-enforced case) or underreacts (leaving a broken cohort under enforcement while only pausing future enrollment, when that cohort itself needs to be pulled back).
- A "manual SSH sessions to enforced hosts trending toward zero" metric needs a legitimate exception path for genuine read-only debugging (viewing logs, checking process state), not a blanket "any SSH access is bad" framing that pushes engineers toward workarounds that are harder to observe than an honest, logged SSH session would have been.
Describe how you modeled Terraform modules for reusable data infrastructure (e.g., S3 buckets, EMR/Dataproc clusters, IAM roles): show module boundaries, variable design, remote state strategy and locking, testing of modules, and how you handled environment-specific (dev/staging/prod) differences and secrets.
Sample Answer
Direct answer
A reusable Terraform module for data infrastructure needs its BOUNDARIES drawn around the resources that genuinely change together as a unit (an S3 bucket plus its own lifecycle policy and encryption config; an EMR/Dataproc cluster plus its own IAM role and security group), with variable design that exposes only what a CONSUMING team actually needs to decide, remote state scoped so a compute cluster's state does not couple to the storage layer's state unnecessarily, and environment-specific differences (sizing, retention, secrets) handled entirely through VARIABLES and per-environment configuration, never through copy-pasted module variants.
Structured elaboration
Module boundaries. Group resources by what actually changes TOGETHER and is meaningfully re-used as a unit: an s3-data-bucket module (bucket, lifecycle policy, encryption, access logging) is one coherent boundary; a spark-cluster module (the EMR/Dataproc cluster itself, its dedicated IAM role, its security group) is another, SEPARATE boundary, even though a given data pipeline consumes both, because a bucket's lifecycle rarely needs to change in lockstep with a cluster's sizing, and coupling them into one module would force every bucket-only change to also touch cluster configuration.
Variable design. Expose the MINIMAL parameter surface a consuming team actually needs to decide (bucket name/prefix, retention period, cluster size, which IAM permissions the cluster needs beyond the module's own sane defaults), keeping everything else (the specific lifecycle-rule structure, the specific encryption algorithm, the specific security-group baseline rules) fixed inside the module so consumers cannot accidentally diverge from the platform's baseline data-governance posture (encryption, retention floors, access logging) the way an unconstrained, fully-parameterized module would allow.
Remote state strategy and locking. Each data-infrastructure COMPONENT (storage, compute) gets its OWN state, following the same per-component isolation principle used generally; a data pipeline's compute layer referencing the storage layer's OUTPUTS (a bucket ARN, for instance) via terraform_remote_state or an explicit variable pass, rather than both living in one combined state file, which would otherwise couple a bucket-retention-policy change's blast radius to the cluster's own apply.
Testing of modules. Module-level integration tests (terratest) provisioning a REAL, ephemeral instance of the module (a genuinely small test bucket, a minimally-sized test cluster) and asserting on its actual configuration (encryption enabled, lifecycle rules present, IAM role scoped correctly), catching a module regression before it reaches any consuming team, run on the module's OWN CI (path-filtered to the module itself), not on every consumer's pipeline.
Handling environment-specific differences and secrets. Environment differences (dev's smaller cluster, prod's stricter retention) are VARIABLE VALUES per environment, never a forked or duplicated module variant; secrets a data pipeline needs (a database credential the cluster reads data from, for instance) are handled through the same referenced-secret pattern used elsewhere, never passed as a raw Terraform variable value that would land in state in plaintext.
Worked example
A concrete module structure for a data pipeline's infrastructure:
modules/
s3-data-bucket/ # bucket, lifecycle, encryption, access logging
spark-cluster/ # EMR/Dataproc cluster, its IAM role, security group
pipelines/
ingestion-pipeline/
dev/main.tf # module "bucket" { source = "../../../modules/s3-data-bucket" retention_days = 7 }
# module "cluster" { source = "../../../modules/spark-cluster" size = "small" }
prod/main.tf # same modules, retention_days = 365, size = "large"
The cluster module's IAM role references the bucket module's OUTPUT (its ARN), passed explicitly as a variable from the consuming pipelines/ingestion-pipeline/*/main.tf (which has access to both modules' outputs within the SAME root configuration), rather than the two modules directly referencing each other, keeping each module independently reusable outside this specific pipeline's combination.
Trade-offs and pitfalls
- Common mistake: bundling storage and compute into ONE module "because this pipeline always uses both together." This couples their state and their change cadence unnecessarily; even when a specific pipeline always pairs them, keeping them as SEPARATE, independently-versioned modules composed together at the pipeline level (as in the worked example) preserves the ability to reuse either one alone in a different context later, and avoids forcing a storage-only change through the compute module's own apply.
- Over-parameterizing a data-infrastructure module (exposing the encryption algorithm, the exact lifecycle-rule shape, as free-form variables) trades platform-team governance for flexibility nobody actually needed; a consuming team should be ABLE to request more permissive settings only through an explicit, reviewed exception, not through an open parameter that quietly lets every consumer set their own baseline.
- Passing a secret value directly as a Terraform variable, even for a "just a connection string" case, lands it in Terraform state in plaintext; a data-pipeline module specifically needs this discipline since data pipelines are exactly the kind of resource that commonly needs database credentials, making this a genuinely common trap for this specific module type.
- Module-level testing costs real money for compute-heavy resources (a test EMR/Dataproc cluster is not free to spin up); sizing the TEST cluster to the smallest viable configuration, and gating the test to run only on changes to the module itself (not on every consuming pipeline's own changes), keeps this cost proportionate.
Create a compliance plan that ensures every infrastructure change is auditable. Include signed commits or tags, branch protection policies, enforced code reviews, immutable release artifacts, retention of CI logs, and centralized change records. How would you demonstrate compliance during an external audit using Git history and CI artifacts?
Sample Answer
Direct answer
Auditable infrastructure change rests on five mechanisms working together, not any single one: signed commits or tags (proving WHO authored a change and that history was not altered after the fact), branch protection (guaranteeing every production-bound change actually went through review), enforced code review (the human judgment layer no automated check replaces), immutable release artifacts (guaranteeing what was reviewed is EXACTLY what got deployed), and CI log retention plus centralized change records (the evidence trail an auditor actually reads). During an external audit, the whole story is told by pointing directly at Git history and CI artifacts rather than a separately maintained change log: git log with signed commits and required-approval metadata IS the change record, and the artifact registry IS the proof of what shipped when.
Structured elaboration
Signed commits or tags. Require GPG- or SSH-signed commits on protected branches (enforced as a required status check, unsigned commits rejected at merge time), so git log --show-signature proves both authorship and that the commit content has not been altered since signing, closing the gap a plain author-name field leaves open (anyone can set their local Git username to anything).
Branch protection policies. Protected branches require at minimum: N approving reviews from someone other than the author, passing status checks (including the policy-as-code and signature checks above), and no force-push or history rewriting. This is what makes "every production-bound change went through review" a structurally enforced fact rather than a documented expectation someone could route around.
Enforced code reviews. Beyond the branch-protection MECHANISM (which enforces that SOME review happened), the POLICY needs to specify who counts as a qualified reviewer for a given path (CODEOWNERS scoping production-infrastructure paths to a smaller, accountable group) and what a reviewer is actually expected to check (a documented review checklist), since an unscoped "any teammate can approve" rule satisfies the branch-protection mechanism without satisfying most compliance frameworks' actual segregation-of-duties intent.
Immutable release artifacts. The artifact that gets deployed (a container image referenced by digest, a Terraform plan file) must be built ONCE, from the reviewed commit, and referenced by an immutable identifier from that point forward; if the artifact could be rebuilt or modified after review, the reviewed diff and the deployed bytes are no longer provably the same thing, which breaks the entire audit chain at its weakest link even if every other control here is correctly implemented.
Retention of CI logs. CI run logs (which checks ran, their results, who triggered the run, exact timestamps) need a retention policy that matches the audit window the compliance framework requires (often one to seven years depending on the regulation), stored somewhere the CI system's own default log rotation will not silently delete before that window closes.
Centralized change records. For most infrastructure-audit purposes, the merged PR itself (title, description, diff, approvals, linked ticket, CI results) IS the centralized change record; a SEPARATE change-management system is only needed if the compliance framework requires change records to exist independently of the engineering tooling itself (some regulated environments do), in which case that system should be populated automatically from the PR/CI data, not maintained as a manually duplicated parallel record that can drift out of sync with what Git actually shows.
Worked example
Demonstrating compliance for a specific past change during an external audit, walking the evidence trail an auditor would actually be shown:
- Find the change.
git log --all --grep="<ticket-id>"or the PR search UI locates the specific merged PR by its linked ticket. - Show the review happened. The PR's approval history (who approved, when, against which commit SHA) demonstrates the required review occurred, and the branch-protection RULE configuration (screenshotted or exported from the Git platform's API) demonstrates that review was structurally REQUIRED, not merely present by coincidence on this one PR.
- Show the commit's integrity.
git log --show-signature <commit-sha>shows the signature verifying both authorship and content integrity. - Show what actually deployed matched what was reviewed. The CI run tied to that exact commit SHA produced an artifact with a specific digest; the deployment record (Argo CD's sync history, or the CI deploy job's log) shows that SAME digest was what actually got applied to production, closing the loop from "this diff was reviewed" to "this exact artifact ran."
- Show the CI checks that gated the merge. The CI run's log (retained per the policy above) shows every required check (policy-as-code, security scan, plan validation) passed before merge was even possible.
Trade-offs and pitfalls
- Common mistake: treating signed commits as sufficient proof of review, when they only prove authorship and integrity, not that review happened. Signing and reviewing are two independent guarantees; both need their own enforcement mechanism (commit signing verification, and branch-protection-required-approvals), and conflating them leaves a real gap an auditor will find.
- A maintained-in-parallel change-management system is a common, avoidable compliance liability. If it is populated by hand rather than automatically from PR/CI events, it WILL eventually drift from what Git actually shows, and an auditor comparing the two systems and finding a discrepancy is a worse outcome than having only the Git-native record in the first place.
- Immutable artifacts are the load-bearing link auditors most often find missing. Even with perfect commit signing and review enforcement, if the deployed artifact could theoretically have been rebuilt from a slightly different commit after review (a mutable tag, a non-reproducible build), the entire chain of evidence has a gap at exactly the step that matters most, "is what I reviewed what actually ran."
- CI log retention needs an explicit owner and a periodic verification that it is actually working, a retention policy that exists only in a document, with nobody having confirmed logs from six months ago are still retrievable, is a compliance gap waiting to be discovered mid-audit rather than beforehand.
Propose how Service Level Objectives (SLOs) and error budgets should be represented, versioned, and deployed via Git workflows alongside infrastructure code. Describe validation steps, who should review SLO changes, how SLO changes propagate to alerting and automation, and how to roll back SLO changes if they cause undesired automation behavior.
Sample Answer
Direct answer
Service-level objectives (SLOs) and error budgets should be represented as PLAIN, VERSION-CONTROLLED DECLARATIVE ARTIFACTS (a YAML or similar spec defining the objective, the underlying service-level indicator query, and the burn-rate alerting thresholds) living in the SAME repository, and going through the SAME PR-and-review workflow, as the infrastructure they govern, deployed to the alerting/automation system by the SAME reconciliation mechanism, not a separate, dashboard-configured, un-versioned side channel. Because an SLO artifact directly controls automated behavior (paging thresholds, and in some organizations automated rollback triggers), its review bar and rollback path need to be at least as rigorous as the infrastructure changes it governs, arguably more so, since a wrong SLO can either cause alert fatigue (too tight) or silently miss real degradation (too loose).
Structured elaboration
Representation. A structured spec per service: the SLI (service-level indicator) query defining what is actually measured (a specific latency percentile, a specific error-rate calculation), the objective threshold and measurement window, and the burn-rate alert thresholds derived from it (fast-burn and slow-burn windows, following the widely-used multi-window burn-rate alerting pattern). This spec is data, not code, so it is reviewable as a clean diff the same way any other declarative configuration is.
Versioning. Committed to Git alongside (or in a clearly cross-referenced sibling path to) the service's own infrastructure definition, so git log on the SLO spec answers "when did this objective change and why" the same way it would for any other infra change, and a service's SLO history is auditable independent of whoever happens to remember the reasoning.
Deployment via Git workflows. A GitOps controller (or a dedicated SLO-config sync job, if the alerting platform is not itself Kubernetes-native) reconciles the deployed alerting-platform configuration to match the Git-declared spec, the same pull-based, continuously-reconciled model already used for application infrastructure generally, so a manually-edited alert threshold in the alerting platform's own UI gets treated as drift, not silently tolerated as a parallel source of truth.
Validation steps. Before merge: schema validation (is the spec well-formed), a SANITY check on the objective itself (is the target achievable given recent actual measured performance, catching an SLO set so tight it would page constantly from day one), and, where the alerting platform supports it, a DRY-RUN evaluation against recent historical data showing what the proposed burn-rate thresholds WOULD have alerted on over, say, the last 30 days, so a reviewer sees concretely whether the change would have caused excessive noise or a dangerous blind spot before it goes live.
Who should review SLO changes. The OWNING team proposes (they have the domain context for what "acceptable" performance means for their service), but a change LOOSENING an existing objective, or changing what a downstream automated system does in response to burn (see below), should require a second reviewer from OUTSIDE the owning team, typically the SRE or platform function with cross-service context, specifically because a team under pressure has an incentive to loosen its own SLO to escape being paged, which is exactly the review-conflict this second-reviewer requirement exists to catch.
How changes propagate to alerting and automation. The reconciler updates the ALERTING PLATFORM's configuration (the actual burn-rate alert rules) directly from the Git-declared spec; any DOWNSTREAM automation keyed off SLO/error-budget state (an automated deployment-freeze trigger when a budget is exhausted, for instance) reads the SAME reconciled objective, so there is exactly one source of truth for "what counts as within budget" feeding every consumer, rather than each consumer holding its own copy that could drift out of sync.
Rolling back an SLO change that causes undesired automation behavior. Because the spec is just a Git-tracked file, rollback is the same git revert plus reconciliation pattern as any other infra change; the practical difference is URGENCY, an SLO change causing a pager storm or, worse, an incorrectly-triggered automated rollback/freeze needs the same fast-path emergency-change mechanism as any infrastructure change: a short-lived, audited bypass with mandatory reconciliation back into Git afterward, since waiting for a normal-cadence PR review while pages fire is not acceptable.
Trade-offs and pitfalls
- Common mistake: configuring SLO thresholds directly in the alerting platform's UI "to iterate quickly," planning to formalize into Git later. This almost never gets formalized in practice, and it recreates exactly the un-auditable, un-reviewable side channel this whole answer exists to prevent; the dry-run-against-historical-data validation step exists specifically to make the Git-first path fast enough that UI-first iteration stops being tempting.
- The second-reviewer requirement for loosening an SLO is the single most-skipped control on this list under deadline pressure, precisely because it exists to catch the exact situation (a team wanting relief from its own pages) where the proposing team has the least incentive to enforce it on themselves.
- A DRY-RUN validation is only as good as the historical window it evaluates against. A recent quiet period can make an objectively too-loose threshold look safe; validating against a window that includes at least one known past incident, where the team can check "would this new threshold have caught it," is a meaningfully stronger check than an arbitrary recent-N-days window.
- Downstream automation consuming SLO state (deployment freezes, automated rollback triggers) needs to fail SAFE if the SLO reconciliation itself is stale or broken, an automation system that silently treats "no recent SLO data" as "budget is fine" can mask exactly the kind of problem it exists to catch; explicit staleness detection on the SLO data feed itself is a real, easy-to-omit requirement.
Unlock Full Question Bank
Get access to all Infrastructure as Code and GitOps interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.