The Production Purity Trap

Stop waiting for production permission. Learn which system beliefs require live traffic and which can be tested safely in isolation.

7 min read

Failure Modes are written from published postmortems, incident write-ups and engineering documentation, which are listed at the foot of every piece. Nothing in this section has been run, measured or operated here — where a number, a threshold or a result appears, it belongs to the source it is credited to.

The Allure of the Real Thing

The argument for production-only chaos engineering is seductive because it feels rigorous. If you want to know if your system survives a database failover, the only way to be sure, the logic goes, is to actually fail over the database while real users are watching. This stance treats production as the only environment where the system is "real." Everything else, from staging to development, is viewed as a toy, a simulation that lacks the weight of actual consequences. This perspective is not without merit. Production environments possess a complexity that is notoriously difficult to replicate elsewhere. The specific combination of network latency, disk I/O contention, memory pressure, and the sheer volume of concurrent requests creates a unique physical reality. A test environment might have the same software version, but it rarely has the same history, the same data distribution, or the same invisible dependencies on third-party services that have drifted over time. When a system runs in production, it is subject to the full force of the laws of physics and network congestion in a way that a lab cannot easily mimic. The SRE book notes that confidence in future reliability is quantified by making predictions from past behavior, and production data provides the most authentic baseline for those predictions.

However, this reverence for production often calcifies into a purity test that paralyzes teams. The requirement that an experiment must be run in production to "count" implies that any other form of testing is invalid. This is a categorical error. It confuses the goal of the exercise, which is to falsify a specific belief about system behavior, with the location of the exercise. If the goal is to verify that a belief is true, the environment must be sufficient to challenge that belief. Insisting on production for every single hypothesis is not just inefficient; it is often dangerous and counterproductive. It raises the barrier to entry so high that many teams never start. They read the principles, look at their production systems, realize they cannot risk a failure, and conclude that chaos engineering is not for them. This is a failure of imagination, not of engineering. The practice is not defined by the environment, but by the quality of the question being asked. If you are asking a question that can be answered without risking user experience, then production is the wrong place to ask it. The insistence on production is a proxy for rigor, but it is a poor one. It mistakes the difficulty of the task for the correctness of the method.

Beliefs That Demand Live Traffic

There are specific classes of beliefs that genuinely require production data to be falsified. These are beliefs about the system’s behavior under real-world load and its interaction with external dependencies that cannot be mocked. For example, if you believe that your service can handle a tenfold spike in traffic without degrading, you cannot prove this in a staging environment that is not receiving actual user traffic. The network paths, the load balancer configurations, and the downstream database capacity are all tuned to real-world patterns. A synthetic load test might mimic the request rate, but it may not mimic the payload sizes, the geographic distribution of users, or the specific mix of API calls. The SRE workbook emphasizes that incident response and monitoring are most effective when they are practiced in the context of real operational conditions. Similarly, if you believe that a specific third-party API is reliable, you cannot test that belief by mocking the API. You need to observe the actual failure modes, the actual latency spikes, and the actual error codes that the provider returns under stress. These are empirical facts that can only be gathered from the live system.

Another class of beliefs that requires production is those related to data integrity and consistency at scale. If you believe that your distributed database maintains strong consistency across regions, you need to test this with real data and real replication lag. The timing of network partitions, the speed of disk writes, and the specific patterns of concurrent updates are all variables that are difficult to replicate in a controlled environment. A simulation might model the logic of the consensus algorithm, but it may not capture the subtle timing issues that arise from hardware variability and network jitter. In these cases, the production environment provides the necessary fidelity. The risk, however, is that these experiments must be carefully designed to minimize impact. They are not random failures; they are targeted probes. The key is to identify these specific, high-value beliefs and to design experiments that can test them with minimal blast radius. This might mean using shadow traffic, canary releases, or targeted latency injection on a small subset of requests. The point is that production is necessary here, but not because it is sacred, and not because it is the only place where truth exists. It is necessary because the belief in question is tied to the specific physical and operational realities of the production environment.

The Value of Simulation and Testing

Most beliefs about system behavior, however, do not require production. They are beliefs about logic, about configuration, about the interaction between components, or about the response to specific, isolated faults. These can be, and should be, tested in non-production environments. Marc Brooker’s work on simple simulations highlights the power of small, readable models for understanding system behavior. He describes how a simple Python simulator of a ski lift queue can reveal counter-intuitive insights about wait times and capacity. The model does not need to be perfect; it needs to be sufficient to answer the specific question being asked. Similarly, a simulation of your service mesh can reveal how a delayed response from one service propagates through the system. It can show where timeouts are triggered, where retries are amplified, and where the system becomes unstable. This is done without touching production, without risking users, and without the political and operational overhead of a live experiment.

The SRE book also distinguishes between traditional tests and production tests. Traditional tests are used to evaluate the correctness of software offline, during development. They are fast, cheap, and can be run thousands of times. They can verify that a specific error handling path is exercised, that a circuit breaker opens under the right conditions, or that a retry policy behaves as expected. These are not "chaos" experiments in the dramatic sense, but they are chaos experiments in the fundamental sense: they are injecting faults to see if the system behaves as expected. If you believe that your system will gracefully degrade when a cache is unavailable, you can test that belief by disabling the cache in a staging environment. If you believe that your logging pipeline will not become a bottleneck under high load, you can test that by generating synthetic log traffic. These tests are valuable precisely because they are isolated. They allow you to focus on the specific mechanism you are interested in, without the noise of the real world. They provide zero MTTR for bugs found, as the SRE book notes, because the bug is caught before it reaches production. This is not a lesser form of testing; it is a more efficient form. It allows you to iterate quickly, to refine your understanding, and to build confidence in the system’s resilience before you ever consider touching production.

Breaking the Purity Test

The insistence on production-only chaos engineering is a barrier to entry that serves no one. It keeps teams from developing the skills and the mindset necessary for operational resilience. It encourages a culture of fear, where any failure is seen as a catastrophe, rather than a learning opportunity. It ignores the fact that most systems are composed of many small parts, and that the interactions between those parts are where the most interesting failures occur. These interactions can be studied in isolation. The first step in chaos engineering is not to break production; it is to understand your system well enough to know what you believe about it. Once you have articulated those beliefs, you can decide which ones require production and which ones do not. For the majority of beliefs, the answer is that they do not. Start with simulations. Start with unit tests that inject faults. Start with integration tests that mimic specific failure modes. Build your confidence in the system’s behavior under controlled conditions. Only when you have exhausted these avenues, and only for the specific beliefs that require it, should you move to production. This approach is not a compromise; it is a strategy. It is a way to build a robust, resilient system that is tested, not just in the real world, but in the mental models that guide its design. The production environment is a tool, not a religion. Use it when it is the right tool, but do not let it prevent you from using the right tools for the job.

What this is built on