Building safe self-healing infrastructure with policy gates and circuit breakers
A developer details a homelab automation stack that auto-remediates service failures while preventing cascading restarts through strict policy gates and verification logic.
A power outage in June revealed a critical flaw in a developer’s home server setup: the reverse proxy failed to restart, cutting off access to all hosted sites. The alert system fired correctly, but the notification channel relied on the very proxy that was down, leaving the owner unaware until evening. This incident sparked the creation of a robust, self-healing infrastructure chain designed to detect and fix such failures automatically without human intervention.
The resulting system reduced recovery time by 17 seconds compared to a hypothetical human operator, but its true value lies in its safety mechanisms. By separating detection from execution and enforcing strict policies, the architecture prevents automated scripts from causing cascading failures during broader outages.
What happened
The developer constructed an auto-remediation pipeline using Prometheus for monitoring, Alertmanager for routing, n8n for workflow orchestration, and a custom policy gate with a restricted executor. The core challenge was not restarting services, which is trivial, but teaching the bot when to refuse action. A naive restart script might loop endlessly if a dependent service like a NAS is down, turning one diagnosable failure into a pile of useless restart logs.
To solve this, the architecture strictly separates roles. Alertmanager sends alerts to n8n, which acts as a coordinator but holds no execution credentials. Instead, n8n queries a policy gate to determine if an action is permitted. Only the gate possesses the credentials to call the executor, which can only run commands from a closed, pre-approved list. This design prevents a compromised or confused orchestrator from executing arbitrary commands, adhering to the principle of least privilege.
The system includes nine possible verdicts from the gate, with only one allowing action. The other eight are refusals, covering scenarios like frozen states, open circuit breakers, or unreachable monitoring systems. This ensures that the automation does not act when it lacks sufficient context or when a deeper underlying cause is already being addressed.
Key details
- Strict role separation: n8n coordinates but cannot execute; only the policy gate holds executor credentials, preventing confused deputy problems.
- Cause hierarchy: The gate recognizes dependency chains, such as a NAS outage freezing multiple services, and refuses to restart individual services when the root cause is known.
- Circuit breakers: Hard limits prevent runaway automation, including caps on actions per service per hour and a fleet-wide failure rate threshold that disarms the system.
- Recovery verification: The system does not trust exit codes; it queries Prometheus to confirm that service probes are actually responding after a restart attempt.
- Canary monitoring: A dedicated metric tracks the last successful end-to-end run of the remediation chain, alerting if the automation itself becomes stale or unresponsive.
- Maintenance mode: Intentional stops for upgrades are handled via a host-level maintenance flag with an expiry time, preventing the bot from restarting services mid-migration.
Background
Self-healing infrastructure aims to reduce mean time to recovery (MTTR) by automating common fixes. However, automation introduces the risk of feedback loops, where a script repeatedly tries to fix a problem that cannot be solved by a restart, such as a network partition or hardware failure. In traditional setups, monitoring tools alert humans, who then diagnose and act. In automated systems, the diagnostic logic must be encoded into the software.
Prometheus is a widely used open-source monitoring system that collects metrics and allows users to define alerts based on query results. Alertmanager handles these alerts, deduplicating and routing them. n8n is a workflow automation tool that can connect different apps and services. By combining these with a custom policy engine, developers can create complex decision trees that mimic human reasoning, such as checking if a dependent service is down before attempting to restart a child service.
Why it matters
For teams running their own software, especially in small to mid-sized companies, reliability often depends on quick responses to incidents. Automation can provide consistent response times regardless of the hour or the availability of staff. The 17-second improvement noted in the case study is less about speed and more about consistency. An automated system performs the same checks and actions at 3 a.m. on a Sunday as it does during business hours, eliminating the variability of human response times.
More importantly, this approach highlights the danger of unchecked automation. Without guardrails, a simple restart script can exacerbate outages. For example, if a storage backend fails, restarting all dependent applications will fail repeatedly, generating noise and potentially masking the real issue. By implementing a policy gate that understands service dependencies and maintains a cause hierarchy, teams can ensure that automation aids rather than hinders incident resolution.
The emphasis on verification over trust is also critical. Many automation tools consider a task complete once the command returns a success code. However, a service may start but remain non-functional due to configuration errors or resource constraints. By requiring external proof of health, such as a successful HTTP probe, the system ensures that the service is truly operational before closing the incident.
What you can do
- Map service dependencies: Identify which services rely on others, such as databases or storage, and ensure your automation checks the health of upstream dependencies before acting on downstream services.
- Implement circuit breakers: Set hard limits on the number of automated actions per service and per fleet within a given time window to prevent runaway loops during sustained outages.
- Verify recovery externally: Do not rely solely on process exit codes; configure your monitoring to confirm that service endpoints are responding correctly after a remediation action.
- Separate coordination from execution: Use distinct credentials for your orchestration layer and your execution layer to limit the blast radius if one component is compromised.
- Monitor the monitor: Create a canary check that verifies your automation pipeline is still running and processing events, alerting you if the self-healing mechanism itself fails.
- Define maintenance windows: Implement a mechanism to signal intentional downtime, such as a file-based flag with an expiry, to prevent automation from interfering with planned updates.



