Chaos Engineering for Kafka
How to break your Kafka platform on purpose, safely and scientifically, so that the real failures of a Tuesday night become boring events instead of front-page outages.
Every building has a fire alarm, and every well-run building also holds fire drills. The alarm proves that a device exists. The drill proves that people know what to do when it rings, that the doors open, that the stairs are not blocked and that the meeting point is real. Many companies run Kafka the way a careless building manager runs a building: the alarms are installed, the diagrams look impressive, and nobody has ever actually walked out.
Kafka is built to survive failure. It copies data to several brokers, elects new leaders when old ones die and lets clients retry. But these promises depend on dozens of settings, on how your applications behave and on your monitoring and people. Chaos engineering is the practice of causing controlled failures to find out whether the promises hold. This guide starts from zero, explains the ideas in simple words and then walks through how to plan, run, measure and automate chaos experiments for Kafka on real infrastructure, including cloud platforms such as AWS.
1Why Kafka Needs Chaos Engineering
Kafka’s design is resilient on paper. Only an experiment can show that your cluster and your applications are resilient in practice.
A quick picture of Kafka
Apache Kafka stores streams of events in named containers called topics, and each topic is split into partitions. The servers that hold partitions are brokers. Programs that write events are producers and programs that read events are consumers. To survive machine failures, every partition is copied to several brokers. These copies are called replicas. One replica is the leader and takes the reads and writes, and the others are followers that keep up by copying from the leader. The followers that are fully caught up form the in-sync replicas, or ISR.
Resilience is a chain, and chains break at the weakest link
Ask a team whether their Kafka setup is highly available and they will usually point to the replication factor of three. That is one link in a long chain. Are the three replicas really in three different zones? Does the producer refuse to accept a write when only one copy exists? Will the consumer application recover if a broker restarts in the middle of a message batch? Does the alert that should wake somebody actually reach a phone? Does the runbook still match the current cluster? A single weak link means the promise is broken, and it is usually the link that nobody has ever tested.
Think of a lifeboat on a ship. The ship has the boat, the boat has the ropes, the crew has a list of who does what, and everyone believes it will work. The only way to learn that a rope has rotted, a pulley is jammed or the crew does not know the list is to lower the lifeboat into the water on a calm day. A chaos experiment is that calm-day test.
Failures you will meet whether you plan for them or not
At scale, failure is not rare. Machines crash, disks fill, network links flap, software is upgraded, certificates expire, cloud zones have bad hours and engineers make mistakes. The question is not whether these events will happen but whether you meet them for the first time during a drill or during a customer-facing outage. Chaos engineering moves that first meeting to the drill.
Chaos engineering is not about causing damage. It is about learning safely. Each experiment asks a clear question about your system, and the answer is either “it held” or “here is a weakness we can now fix.”
The hidden cost of never testing
Skipping resilience testing feels free, but the cost simply moves to a later and worse moment. A first failover that happens at three in the morning on a Saturday is run by tired people, without a rehearsed plan, while customers are watching. The same failover run on a Tuesday afternoon in a drill is run by rested people who have a plan and a stopwatch. The failure is identical. The outcome, and the price, are very different.
There is also a quiet cost in confidence. Teams that have never seen their system fail well tend to be afraid of every change. They delay upgrades, avoid restarts and keep old versions running, and that fear creates its own risk. Teams that practice failure develop calm. They know how the system behaves when it is hurt, so they are willing to improve it.
2Chaos Engineering From Zero
Before applying the ideas to Kafka, understand where they came from and what makes an experiment “chaos engineering” rather than just breaking things.
A short history
The practice began at Netflix. When Netflix moved from its own data centres to the cloud around 2010, engineers realized that cloud machines can disappear at any time. Instead of hoping for the best, they built a tool called Chaos Monkey that randomly terminated virtual machines during working hours, so that every team was forced to build services that survived losing a machine. Over time the tool family grew, and the discipline was described in a set of ideas known as the principles of chaos engineering and later in a book written by Netflix engineers. Today the approach is used across banks, retailers, streaming companies and cloud providers, and several tools and cloud services exist to support it.
The five principles in plain words
Start from steady state
Define what “working normally” looks like with numbers, such as success rate and latency, before you break anything.
Form a hypothesis
Predict what will happen: “if a broker dies, producers will see no errors and lag will stay under a minute.”
Use real-world events
Inject faults that really happen: crashed machines, slow networks, full disks, expired certificates.
Limit the blast radius
Start small, watch closely and have a way to stop at once. Grow only when the small step is safe.
Automate and repeat
A system changes every week. An experiment that passed last year proves little about today, so repeat it regularly.
Chaos engineering is not random destruction
The word “chaos” sounds reckless, but the practice is careful and scientific. A scientist changes one variable, watches the results and compares them with a prediction. A chaos engineer does the same. Random breaking without a hypothesis, without measurements and without a stop button is simply an outage created by yourself. The difference between the two is discipline.
flowchart LR
A["Define steady state with metrics"] --> B["Write a hypothesis"]
B --> C["Plan scope, blast radius and abort rules"]
C --> D["Inject the fault"]
D --> E["Observe metrics, logs and client behavior"]
E --> F{"Did the system stay within limits?"}
F -->|Yes| G["Record success and raise the difficulty"]
F -->|No| H["Abort, restore and analyze the weakness"]
H --> I["Fix the design, settings or runbook"]
I --> A
G --> A
Related practices, so you can tell them apart
| Practice | Main question | How it differs from chaos engineering |
|---|---|---|
| Unit and integration testing | Does this piece of code do what I wrote? | Tests known behavior in controlled conditions, rarely under failure of the surrounding system |
| Load testing | How much traffic can the system take? | Adds pressure but usually no faults; the two are often combined |
| Disaster recovery drills | Can we restore service after a large-scale loss? | Tests big scenarios, usually less often and with a plan known in advance |
| Game days | Can the team respond to a simulated incident? | A format for running chaos experiments with people involved |
| Fault injection testing | What happens if this specific call fails? | A technique that chaos engineering uses inside a broader, hypothesis-driven practice |
A good answer to “What is chaos engineering?” names the loop: define steady state, form a hypothesis, inject a real-world fault with limited blast radius, observe, and improve. Add that its goal is confidence in the system, not damage.
Objections you will hear, and honest answers
| Objection | Honest answer |
|---|---|
| “We are too small for this.” | Small teams have fewer people to respond to an outage, so rehearsal matters more. A single broker-stop drill in a test cluster costs an afternoon. |
| “Kafka is already fault tolerant.” | Kafka provides the mechanisms. Your settings, clients, network and people decide whether they work together. |
| “We cannot risk production.” | Then start in staging, and grow carefully. Not testing does not remove the risk. It only postpones your first look at it. |
| “We passed load tests.” | Load tests rarely include failures. Most outages happen when load and failure meet. |
| “We do not have time.” | Compare the time with the length of one avoidable outage, including the follow-up meetings and lost trust. |
| “Our cloud provider handles it.” | Providers protect their layer. Your applications, settings and dependencies remain your responsibility. |
3What Kafka Promises, and How Promises Break
Chaos experiments test promises. So first list the promises Kafka makes, and the conditions each one depends on.
The main guarantees
| Promise | What it depends on | How it can quietly fail |
|---|---|---|
| Order within a partition | Producer settings for retries and in-flight requests, and one leader per partition | Retries without safe settings can reorder messages after a failure |
| Acknowledged data is not lost | The producer waiting for all in-sync replicas, a sensible minimum ISR, and unclean leader election turned off | A minimum ISR of one lets a single copy accept writes, which a crash can destroy |
| Availability during a broker loss | Replication factor, replicas in different zones, enough spare capacity | Replicas that share a zone or rack fail together |
| Consumers do not miss data | Correct offset handling and retention long enough for consumers to recover | Consumers that fall behind past retention lose data silently |
| Exactly-once results (where used) | Idempotent producers, transactions and consumers that read only committed data | Side effects outside Kafka, such as calls to databases, are not covered |
| Timely recovery | Controller failover, client retry settings, monitoring and runbooks | Timeouts and retry limits too short for the real recovery time |
Delivery semantics in simple words
Three terms describe what a consumer sees after a failure. At-most-once means a message may be lost but is never seen twice. At-least-once means a message is never lost but may be seen more than once. Exactly-once means each message affects the result exactly one time. The default and most common setup is at-least-once, and it means consumers must be safe against duplicates. This is a classic thing to check with chaos: kill a consumer at a bad moment and see whether the results are counted twice.
Imagine a post office that promises to deliver every parcel. If a courier’s van breaks down halfway, the office may send a second van with a copy of the parcels to be safe. The customer might then get two parcels. If the customer’s system counts each parcel as a separate order, they are charged twice. The promise “never lose a parcel” was kept, but the customer’s system did not plan for duplicates.
Where promises are set: a settings map
Many of Kafka’s promises are controlled by a small group of settings. Chaos experiments are the best way to prove that these settings are right for your needs.
Replication factor and minimum ISR
How many copies exist and how many must be in sync for a write to be accepted.
Unclean leader election
Whether an out-of-date replica may become leader. Off protects data, on protects availability.
Rack awareness
Whether replicas of one partition are spread across zones.
Acknowledgments, retries, idempotence, timeouts
How sure the producer wants to be, and how long it keeps trying before giving up.
Session timeout, poll interval, offset commit style
How quickly a failed consumer is replaced, and how the consumer records progress.
Controller quorum and timeouts
How fast the cluster notices a dead broker and how many controllers must survive.
A setting can be correct on the broker and wrong in a client, or the other way around. A durable topic does not help if the producer only waits for the leader. Test the whole path from application to disk and back, not just the cluster.
Consistency and availability in plain words
A distributed system that copies data to several places faces a hard choice when the network breaks. It can keep accepting writes and risk the copies disagreeing, or it can refuse some writes and keep the copies consistent. This trade-off is often called the CAP theorem, and its practical meaning is simple: during a partition, you cannot have both perfect availability and perfect consistency. Kafka lets you choose a point on this line through its settings.
With strict settings, meaning acknowledgment from all in-sync replicas, a minimum ISR of two and no unclean leader election, Kafka favors consistency. During a partition, some writes are refused so that no acknowledged message is lost. With relaxed settings, Kafka favors availability. It keeps accepting writes, but acknowledged data may be lost when leaders change. Neither choice is universally right. A log of clicks for analytics can tolerate loss, while a ledger of payments cannot. Chaos experiments show you which choice your cluster actually makes, which is sometimes not the one you thought you configured.
Two bank branches share a ledger and the phone line between them goes dead. Either both branches keep serving customers and risk contradicting each other, or one branch stops serving customers until the line returns. Kafka’s settings decide which of these two branches you have built.
4The Anatomy of a Kafka System and Where It Can Fail
A Kafka platform is more than a set of brokers. Draw the whole picture before choosing what to break.
flowchart LR
PROD["Producer applications"] --> DNS["DNS and load balancer"]
DNS --> B1
DNS --> B2
DNS --> B3
subgraph AZA["Zone A"]
B1["Broker 1"]
end
subgraph AZB["Zone B"]
B2["Broker 2"]
end
subgraph AZC["Zone C"]
B3["Broker 3"]
end
CTRL["Controller quorum"] --- B1
CTRL --- B2
CTRL --- B3
B1 --> CONS["Consumer applications"]
B2 --> CONS
B3 --> CONS
SR["Schema registry"] --- PROD
SR --- CONS
CON["Connect workers"] --- B2
MON["Monitoring and alerting"] --- B1
MON --- B2
MON --- B3
A map of failure points
| Layer | Examples of faults | Why it matters |
|---|---|---|
| Machines and processes | Broker crash, forced termination, out-of-memory, long pauses | Tests leader election, ISR handling and client retries |
| Storage | Full disk, slow disk, failed volume | Tests log directory handling and recovery time |
| Network | Latency, packet loss, partitions between brokers, zones or clients | Tests replication lag, ISR stability and consumer group timeouts |
| Control plane | Controller failure, loss of quorum majority | Tests how the cluster behaves when it cannot make metadata changes |
| Clients | Producer crash, consumer crash, slow consumer, poison message | Tests application logic for duplicates, ordering and lag |
| Dependencies | Schema registry down, DNS failure, secrets store unavailable, certificate expiry | Tests hidden single points of failure around Kafka |
| People and process | Wrong configuration, mistaken deletion, failed upgrade | Tests runbooks, alerts and permissions |
| Environment | Zone outage, cloud service degradation | Tests the assumptions behind your architecture |
Think in terms of dependencies
A helpful exercise is to trace one business event through the whole system. Take “a customer places an order.” Which producer sends it? Through which network path? To which topic and partition? Who is the leader, where are the followers, and who reads it next? Where does the result go, and who depends on that result? Every arrow on that path is a dependency, and every dependency is a candidate for an experiment. Teams often discover in this exercise that a supposedly independent service silently depends on a single machine, a single DNS name or a single person.
Keep a living diagram of dependencies with a column for “last tested.” Any arrow that has never been tested is your next candidate experiment.
A worked dependency trace
Take the event “customer places an order” in an imaginary shop. The web service creates the event and sends it through a load balancer to a producer library, which writes it to the orders topic. The leader of the chosen partition, say on broker 2 in Zone B, appends it and waits for followers in Zones A and C. A stream application reads the topic, enriches each order with customer data from a database, and writes the result to a second topic. A connector copies that topic into a warehouse, and a dashboard reads the warehouse. Count the components on this path: at least ten, spread over three zones and four teams. Each one can slow, stop or misbehave, and each arrow between them can break. Writing this path on a whiteboard, with a red dot on every arrow that has never been tested, usually produces a very long list of candidate experiments and a healthy sense of humility.
5Defining Steady State: What “Normal” Looks Like
You cannot tell whether an experiment hurt the system unless you know precisely what a healthy system looks like.
Measure what users feel, not only what servers do
A common mistake is to define steady state only with server metrics such as processor use. Users and downstream applications do not care about processor use. They care whether their events are accepted quickly and whether results arrive on time. Good steady-state measures come in two groups. Outcome measures describe what applications and users experience. Health measures describe the internal condition of the cluster and help explain why an outcome changed.
| Type | Measure | Healthy state (example thresholds) |
|---|---|---|
| Outcome | Producer success rate | Above 99.9 percent of sends accepted within the timeout |
| Outcome | End-to-end latency from produce to consume | 99th percentile under an agreed limit, for example 500 milliseconds |
| Outcome | Consumer lag on critical groups | Below a limit in seconds of data, not just message count |
| Outcome | Business result rate | Orders processed per minute within a normal band |
| Health | Under-replicated partitions | Zero |
| Health | Offline partitions | Zero |
| Health | Active controller count | Exactly one |
| Health | In-sync set shrink and expand rate | Near zero in calm periods |
| Health | Request latency at high percentiles | Within baseline range |
| Health | Request handler and network idle percentage | Comfortably above zero, showing spare capacity |
| Health | Disk and network usage | Below planned limits |
Build a canary: a tiny producer and consumer that never stop
The best single steady-state signal is a canary. This is a tiny producer that writes a timestamped message to a special topic every second, paired with a tiny consumer that reads it and computes how long the trip took. The canary measures the whole path, including the broker, the network and the client libraries, from the point of view of an ordinary client. It gives you a clean line on a graph that jumps the moment something is wrong. Open-source tools exist for this idea, such as the Kafka monitor project that started at LinkedIn, and many teams write their own in an afternoon.
Before a big concert, a sound engineer speaks into every microphone and listens to every speaker. That test voice is a canary. If it sounds fine, the system works from mouth to ear. If it crackles, you know at once, even before the audience notices.
Know your natural variation
Every metric wiggles. Latency is a little higher at peak hour, and lag rises when a big batch job runs. If you do not know the normal wiggle, you will mistake normal variation for damage, or damage for variation. Study at least a couple of weeks of history and write down the normal range for each measure at the hour and day you plan to run the experiment. Experiments should compare against that range, not against a single perfect number.
Use service level objectives
A service level objective, or SLO, is a written target for a user-facing measure, for example “99.9 percent of events are consumed within two seconds.” SLOs give you an honest yardstick for experiments. If the hypothesis is “a broker failure does not breach our SLO,” you can decide clearly whether the experiment passed. SLOs also define an error budget, the small amount of allowed failure. Many teams spend a slice of that budget deliberately on chaos experiments, since the learning is worth more than the small risk.
Do not begin an experiment while the system is already unhealthy. A cluster with existing under-replicated partitions or a recent incident is not in steady state, and any result you collect will be confusing. Make a “steady state check” the first step of every run.
An example service level objective set for a Kafka platform
| Objective | Target | Measured by |
|---|---|---|
| Produce availability | 99.9 percent of send attempts succeed within the delivery timeout, measured monthly | Canary producer and application error counters |
| End-to-end latency | 99 percent of canary messages consumed within one second | Canary consumer timestamps |
| Durability | Zero acknowledged messages lost on topics marked critical | Integrity auditor |
| Recovery from single broker failure | Client errors end within one minute, full replication returns within fifteen minutes of restart | Experiment timings and cluster metrics |
| Consumer freshness for critical groups | Lag under two minutes of data at 99 percent of samples | Lag exporter converted to time |
These numbers are examples. Your own targets should come from what your business needs and what your architecture can honestly deliver. What matters is that they are written down, measurable and agreed, so that an experiment can be judged against them without argument.
6Writing Good Hypotheses and Experiment Plans
A hypothesis turns “let us break something” into “let us learn something.” It also makes the result unambiguous.
The shape of a good hypothesis
A good hypothesis has four parts. It names the fault, it names the measure that should stay healthy, it gives a limit in numbers and it gives a time for recovery. For example: “When one broker in Zone B is forcibly stopped, the producer success rate stays above 99.9 percent, the 99th percentile end-to-end latency stays below one second after the first 30 seconds, no acknowledged message is lost, and all partitions return to full replication within ten minutes of the broker returning.”
| Weak hypothesis | Why it is weak | Stronger version |
|---|---|---|
| “Kafka should handle a broker failure.” | No measure, no limit, no time | “After one broker is stopped, produce errors stay below 0.1 percent and lag recovers within five minutes.” |
| “The network is reliable enough.” | Not testable | “With 200 milliseconds of added latency between Zone A and Zone C, in-sync sets do not shrink and end-to-end latency stays under two seconds.” |
| “Consumers recover on their own.” | No definition of recover | “After a consumer instance is killed, its partitions are reassigned within 45 seconds and no result is counted twice.” |
| “Alerts work.” | Vague | “When two brokers are unreachable, the on-call phone rings within three minutes and the runbook link opens the correct page.” |
The experiment card
Write every experiment on a one-page card, so anyone can understand and approve it. The card should be short enough to read in two minutes.
Name and owner
A clear title and one accountable person.
Hypothesis
The prediction, with measures, limits and times.
Scope and blast radius
Exactly which brokers, topics, clients or zones are involved.
Fault and duration
What will be injected, how strongly, and for how long.
Abort conditions
The measured thresholds that stop the run at once.
Rollback steps
How to undo the fault and how to check the system is normal again.
Observers and channels
Who is watching which dashboard, and where messages go.
Notifications
Which teams and on-call people are told before and after.
Ask “what will we do with the answer?”
Before running any experiment, ask what you will change if it fails and what you will conclude if it passes. If you cannot answer either, the experiment is probably not worth running. Experiments should guide decisions: change a setting, add a runbook, retire a risky design or add a monitor.
Example: a card for a controller failover test
Title: “Kill the active controller during normal traffic.” Hypothesis: the cluster elects a new active controller within a few seconds, no producer sees more than a brief spike in errors, and topic creation works again within one minute. Scope: one cluster in the pre-production environment. Abort if produce success drops below 95 percent for more than one minute. Rollback: restart the stopped node. Observers: the platform lead watches controller metrics, an application owner watches client errors.
Choosing which experiment to run first
You cannot test everything at once, so rank candidate experiments. Score each one on three simple questions: how likely is this failure in real life, how bad would the impact be, and how uncertain are we about the outcome? Failures that are likely, harmful and poorly understood go to the top. A broker crash is likely and moderately harmful, so it comes early. A slow disk on one broker is fairly likely and can be very harmful because it is hard to detect, so it also ranks high. A total loss of a region is very harmful but rare, so it belongs on the yearly schedule. This ranking gives a simple, defensible plan for the first year.
| Candidate | Likelihood | Impact | Uncertainty | Priority |
|---|---|---|---|---|
| Stop one broker | High | Medium | Medium | Run first |
| Consumer crash mid-processing | High | Medium | High | Run first |
| Slow disk on one broker | Medium | High | High | Run early |
| Certificate expiry | Certain over time | High | Medium | Run early |
| Network delay between zones | Medium | Medium | High | Run early |
| Lose a full zone | Low | High | High | Schedule yearly |
| Regional failover | Very low | Very high | Very high | Schedule yearly, with rehearsal |
7Blast Radius, Safety and Abort Conditions
The skill that separates chaos engineering from vandalism is control. You must always be able to stop.
Grow the blast radius in rings
The blast radius of an experiment is the amount of the system, and the number of users, that it can affect. Begin with the smallest radius that still teaches you something, and grow it in stages only when the earlier stage is understood.
flowchart TB
R1["Ring 1: local or throwaway cluster, no real users"] --> R2["Ring 2: shared staging cluster with test traffic"]
R2 --> R3["Ring 3: production canary topics or one low-risk consumer group"]
R3 --> R4["Ring 4: one production broker during off-peak hours"]
R4 --> R5["Ring 5: a full zone or a full failover, planned and announced"]
Abort conditions: the stop button
Every experiment needs written, measurable conditions under which it stops immediately. Examples are “produce success below 95 percent for 60 seconds,” “any offline partition on a critical topic,” “consumer lag on the payments group above five minutes” or “any customer-facing alert fires.” Wire these conditions into automation when you can, so that the fault is removed automatically even if no person is watching. Cloud fault-injection services support this idea with alarms that stop an experiment when triggered, and open-source tools can be scripted to do the same.
Safety checklist before every run
Steady state confirmed
Dashboards are green, and no incident or deployment is in progress.
Approvals and notice
The right owners have agreed and affected teams know the window.
Backups and recovery ready
Recent configuration is saved, and the rollback path was tested.
Abort rules armed
Alarms and manual stop procedures are in place and tested.
People in place
Observers, an experiment lead and an incident commander are named and available.
Timing chosen wisely
Avoid peak traffic, holidays, freezes and the hours before a major release.
Protect data
Some faults can destroy data permanently, such as deleting a broker’s log directory or corrupting files. Run these only in environments where the data is disposable or fully backed up. In production, prefer faults that are reversible: stopping a process, adding latency, blocking a port or pausing a disk. If the answer you need can be found with a reversible fault, do not use an irreversible one.
Protect the chaos tools themselves
A tool that can stop machines and change networks is powerful, and therefore a security risk. Give it the least permissions it needs, limit its targets by tags or names, log every action it takes, and require approval for production use. An attacker or a careless user who controls the chaos tool controls the outage button.
Do not run a new experiment on production for the first time during a busy period, without notice, or by a single person who is also the only person watching. Two sets of eyes and a written stop rule are the minimum.
Approvals and communication
Production experiments belong in the same change management process as any other risky change. Write a short notice that says what will happen, when, how long, what the expected impact is and who to contact. Send it to the owners of every application that uses the cluster, the on-call team and the support desk. On the day, post a message when the experiment starts, when it ends and when the system is confirmed healthy. This transparency turns a possible source of panic into an ordinary scheduled event.
| Item in the notice | Example |
|---|---|
| What | One broker in the production cluster will be stopped for five minutes |
| When | Wednesday 10:00 to 10:30, a low-traffic window |
| Expected impact | Brief producer retries, no data loss expected |
| Stop rule | Success rate below 95 percent for one minute, or any customer alert |
| Contacts | Experiment lead and on-call engineer with phone numbers |
| Rollback | Restart the broker, confirm replicas are in sync |
8Experiments on Brokers and Controllers
Losing a broker is the most natural test for Kafka, and it teaches a great deal.
Experiment 1: stop a follower broker
Choose a broker that leads few partitions and stop its process abruptly. The cluster should keep serving all partitions, because other replicas exist. Leaders of the partitions on that broker do not change, but the in-sync set of each partition shrinks. Producers with strict acknowledgment settings still succeed as long as enough copies remain, given by the minimum ISR. Check that no under-replicated alert is missed, and that when the broker returns it catches up and rejoins every in-sync set.
Experiment 2: stop a leader-heavy broker
Now stop a broker that leads many partitions. This is a harder test. The controller must elect new leaders for all of them, and clients must find the new leaders through a metadata refresh. Expect a brief burst of errors and latency. Measure how long the burst lasts, how many messages the producers retried and whether any application gave up too soon. The result gives you the real number for “how long is our failover” instead of a guess.
sequenceDiagram
participant X as Chaos Tool
participant B as Broker 2 target
participant C as Controller
participant P as Producer
participant M as Monitoring
M->>M: Confirm steady state
X->>B: Stop the process abruptly
C->>C: Detect missing broker
C->>C: Elect new leaders for its partitions
P->>P: Errors, metadata refresh, retries
P->>C: Ask for updated metadata
P->>P: Sends succeed on new leaders
M->>M: Check abort rules and record timings
X->>B: Restart the process
B->>C: Rejoin and catch up
M->>M: Confirm full replication and balanced leaders
Experiment 3: repeated restarts (a rolling failure)
Real life often brings not one failure but several in a row: a rolling upgrade, an autoscaling event or a bad deployment. Restart brokers one after another with only a short pause between them, or restart the next before the previous one has fully caught up. This tests what happens when the cluster is still recovering while another broker leaves. It often reveals that the minimum ISR setting, or the amount of spare capacity, is tighter than assumed.
Experiment 4: kill the active controller
In a modern cluster with a controller quorum, terminate the active controller node. The remaining controllers elect a new one. The hypothesis is that brokers keep serving data during the change and that cluster-wide operations, such as creating a topic, recover within a short time. Then try the harder version: stop enough controllers to lose the majority. The expectation is that data traffic on existing partitions keeps flowing from the brokers’ local state, but no metadata changes are possible, no new leader can be elected, and any broker failure at that time causes lasting unavailability of its partitions. This experiment proves why the quorum should be spread across zones.
Experiment 5: controlled shutdown versus crash
Compare a gentle shutdown with a crash. In a gentle shutdown, the broker asks the controller to move its leaders away first, and clients see very little. In a crash, leaders vanish suddenly. Running both tells you how much your maintenance procedures protect users, and how much worse an unplanned failure is.
| Fault | Expected Kafka behavior | What to verify | Common surprise |
|---|---|---|---|
| Follower stops | ISR shrinks, service continues | Alerts fire, no producer errors, fast catch-up | Minimum ISR set to one hides the risk |
| Leader-heavy broker stops | Elections, short burst of errors | Failover time and client retry success | Clients give up before the election completes |
| Rolling restarts too fast | Partitions fall below minimum ISR | Write availability and catch-up throttling | Restarting the next broker before replicas are in sync |
| Active controller stops | New controller elected quickly | Metadata operations resume, no data loss | Monitoring shows two controllers or none for a while |
| Controller majority lost | No metadata changes possible | Existing traffic continues, alerts fire | Runbook does not cover this case |
| Broker returns after long outage | Heavy catch-up traffic | Impact of catch-up on other traffic | Catch-up saturates the network or disks |
Record four numbers in every broker experiment: time to detect the failure, time to complete leader elections, time for clients to fully recover and time for replicas to return to full sync. These four numbers, tracked across experiments, are the real measure of your availability.
Experiment 5b: watching unclean leader election in a lab
A special experiment is worth running only in a disposable test cluster. Turn on unclean leader election for one test topic, and use a network block to make the followers fall behind while the leader keeps accepting writes. Then stop the leader. Because no in-sync follower remains, the cluster may promote an out-of-date replica as the new leader. Send verification messages before and after, and use the auditor to see how many acknowledged messages vanished. The result gives your team a memorable, first-hand picture of why this setting is usually kept off for important data, and why “availability at any cost” has a real cost.
Repeat the same run with the setting off. The partition should stay unavailable for writes until an in-sync replica returns, but no acknowledged message is lost. Seeing both runs side by side makes the trade-off concrete for engineers and managers alike.
9Network Chaos: Latency, Loss and Partitions
Networks fail in messy, partial ways. Those partial failures are much harder on Kafka than a clean crash.
Why partial failures are harder than crashes
When a machine is completely dead, everybody agrees that it is dead. When a machine is slow, or when it can talk to some peers but not others, different parts of the system disagree about its state. One broker thinks a follower is fine, while the controller thinks it is gone, and a client sees timeouts. These disagreements cause flapping in-sync sets, repeated leader elections and confusing symptoms. Engineers call this a gray failure: not down, not healthy, just wrong.
Experiment 6: added latency between zones
Add 100 to 300 milliseconds of delay to traffic between two zones. Followers in the far zone now take longer to fetch, so replication lag grows and end-to-end latency rises for writes that wait for all in-sync replicas. Watch whether followers fall out of the in-sync set, which depends on the lag limit setting, and whether producers with strict settings slow down or fail. The hypothesis to test is that your latency budget can absorb realistic cross-zone slowdowns.
Experiment 7: packet loss
Drop a small percentage of packets, for example two to five percent, on the path between brokers or between clients and brokers. Loss forces retransmissions and makes every request slower and less predictable. The interesting result is not whether Kafka survives but how gracefully: do timeouts, retry settings and consumer session settings turn a slow network into a storm of rebalances and duplicate processing?
Experiment 8: network partition
Block traffic between groups of nodes completely. There are several shapes to try.
flowchart LR
subgraph ZA["Zone A"]
A1["Broker 1 leader"]
AP["Producer"]
end
subgraph ZB["Zone B"]
B1["Broker 2 follower"]
end
subgraph ZC["Zone C"]
C1["Broker 3 follower"]
CT["Controller"]
end
AP --> A1
A1 -. "blocked link" .- B1
A1 --> C1
CT --> A1
CT --> B1
CT --> C1
Leader isolated from followers
The leader keeps accepting writes but cannot replicate. With safe settings, writes fail instead of being accepted on one copy.
Broker isolated from controller
The broker is alive but cannot reach the control plane, so it may be fenced and its leaders moved while it still thinks it is in charge.
Clients isolated from some brokers
Some clients can reach only part of the cluster. Watch for retry storms and metadata churn.
Zone cut off
A whole zone loses contact. With replicas in three zones and a minimum ISR of two, service should continue on the majority side.
What safe settings should show
With acknowledgment from all in-sync replicas, a minimum ISR of two out of three and unclean leader election turned off, a partition that loses contact with two of its three replicas should stop accepting writes rather than accept them on a single copy. Producers receive errors such as “not enough replicas.” That is a correct outcome: the system chose consistency over availability for that partition. Your job is to check that the application handles the errors well, buffers or backs off, and does not silently drop data.
| Setting combination | Behavior during a partition | Risk |
|---|---|---|
| Acknowledgment from leader only, minimum ISR of one | Leader keeps accepting writes with a single copy | Data loss if the isolated leader is lost or replaced |
| All-replica acknowledgment, minimum ISR of one | Writes accepted with only the leader in sync | Same risk, hidden behind a stricter-sounding setting |
| All-replica acknowledgment, minimum ISR of two | Writes rejected when fewer than two copies are in sync | Reduced availability but protected data |
| Unclean leader election allowed | An out-of-date replica can become leader | Loss of acknowledged data, possible divergence |
Picture three clerks who each keep a copy of a ledger and must agree before any entry is final. If one clerk is cut off by a locked door, the other two can still agree and carry on. If two clerks are cut off, the remaining clerk should refuse new entries, since nobody can confirm them. Accepting entries alone would let the ledgers drift apart.
Network chaos should be applied at the narrowest level that answers your question, for example one pair of nodes, and with a timer that removes the fault automatically. A fault left in place because someone forgot the cleanup step is a common cause of real incidents that start as experiments.
How to inject network faults safely
On Linux machines, the traffic control features of the operating system can add delay, loss and bandwidth limits to a network interface, and firewall rules can block chosen addresses or ports. These are simple and powerful, and they are also dangerous because a mistake can cut off your own access to the machine. Three habits reduce the risk. First, always attach a timer so the fault removes itself, for example by scheduling the cleanup command at the same moment you start the fault. Second, apply the fault only to traffic between the specific addresses you are testing, never to the management interface you use to log in. Third, keep an out-of-band way into the machine, such as a console, in case the fault locks you out. In Kubernetes and cloud environments, chaos tools and fault services wrap these steps with scoping and automatic cleanup, which is one good reason to adopt them as the practice matures.
10Disk, Memory and Processor Chaos
Brokers live on disks and depend on memory and processors. Stress these and you see how Kafka behaves when the machine, not the network, is the problem.
Experiment 9: slow disk
Kafka writes to disk all day, and it reads old data from disk whenever consumers fall behind. Slow the disk down, either with a tool that adds delay to file operations or, in the cloud, by pausing input and output on a volume for a short time. Watch the request latency at high percentiles, the time followers take to catch up and the speed at which lagging consumers can read. A slow disk on one broker often causes more harm than a dead broker, because the cluster keeps sending it work. This experiment reveals whether your monitoring can tell “slow” from “healthy.”
Experiment 10: disk full
Fill a data disk in a test environment until only a tiny amount of space is left. When a log directory can no longer be written, the broker can no longer serve partitions stored there. With several data directories, modern Kafka can mark the failing directory as offline and keep the other directories running. With a single directory, the broker typically shuts down. The experiment shows whether alerts fire early enough, whether retention settings free space in time and whether the runbook for freeing space is correct and safe to follow under stress.
Never fill a production disk to test this. Instead, test in a copy of the environment, or reduce the free-space thresholds of your alerts and simulate the condition with a small test volume.
Experiment 11: memory pressure and long pauses
Restrict the memory available to a broker, or induce long garbage collection pauses by stressing the heap. A paused broker looks dead to the cluster without actually being dead, and after the pause it returns with stale ideas about who leads what. Watch whether brokers get fenced, whether leader changes cause client errors and whether the returning broker recovers cleanly. The companion guide on diagnosing broker GC pauses goes deep into this class of faults.
Experiment 12: processor starvation
Consume most of the processor time on one broker with a stress tool. Request handler threads then wait for processor time, queues grow and latency rises. On virtual machines this imitates a noisy neighbor. The hypothesis to test is whether your cluster spreads work sensibly, whether alerts identify the struggling node and whether operators can drain leaders from it quickly.
Experiment 13: clock skew
Move a broker’s clock forward or back by minutes. Time affects retention decisions based on message timestamps, security certificates, token lifetimes and some timeouts. Clock skew experiments often reveal surprises in log deletion timing and in authentication. Run them in staging first.
| Fault | Typical injection method | Main things to watch |
|---|---|---|
| Slow disk | File-system delay tool, volume input and output pause | High percentile request time, follower lag, alert quality |
| Full disk | Small test volume filled with data | Log directory failure handling, retention, runbook |
| Memory pressure | Lowered memory limit, stress tool | Pauses, fencing, out-of-memory kills, restarts |
| Processor starvation | Stress tool, quota reduction | Queue times, idle percentages, leader draining |
| Clock skew | Time offset tool on one node | Retention behavior, certificate and token checks |
Example: the slow volume on a cloud broker
A team pauses input and output on one broker’s volume for 30 seconds during a test window. They expect the cluster to route around the slow broker. Instead, producers with leaders on that broker time out, followers on other brokers fall behind because they cannot fetch, and the alert for slow disks never fires because it only watches disk usage, not disk latency. The team adds a disk latency alert, shortens the leader drain procedure, and repeats the test successfully the following week.
11Client Chaos: Producers and Consumers
Most of the data loss and duplication in real Kafka systems is caused by applications, not brokers. Test the applications too.
Producer experiments
Producer crash mid-batch
Kill a producer while it is sending. Check that the application either resends unacknowledged events or the source system replays them, and that duplicates are harmless.
Broker unavailable for longer than the timeout
Stop the broker long enough to exceed the producer’s delivery timeout. The application should handle the failure by buffering, alerting or failing loudly, not by dropping events quietly.
Retries with ordering
Cause a transient error and check that events for a key are still in order when retries happen. This depends on idempotence and in-flight settings.
Buffer exhaustion
Slow the brokers so the producer’s buffer fills. Check whether the application blocks, fails or loses events.
Consumer experiments
Consumer crash during processing
Kill an instance after it processed a message but before it saved its position. Another instance will process the message again. Confirm that results are not doubled.
Rebalance storm
Restart many consumer instances at once. Watch how long the group is idle and whether lag recovers.
Slow consumer
Make processing slower than the interval limit. The group may decide the consumer is dead and reassign its partitions repeatedly.
Poison message
Inject a message that always makes the consumer fail. Check that the application skips it, moves it to a dead-letter topic and continues, rather than getting stuck forever.
Lag, retention and the point of no return
If a consumer group stays down longer than the topic’s retention, the data it needs is deleted before it reads it. The group then restarts from its reset policy, either the beginning or the end, and either reprocesses a huge amount or skips a huge amount. A useful experiment is to stop a non-critical consumer group for longer than expected and check that alerts warn about lag well before it reaches the retention limit, and that the recovery procedure is documented.
sequenceDiagram
participant Q as Topic partition
participant C1 as Consumer 1
participant C2 as Consumer 2
participant DB as Result store
Q->>C1: Deliver message 41
C1->>DB: Write result for message 41
Note over C1: Crash before saving position
Q->>C2: Group reassigns partition, deliver message 41 again
C2->>DB: Write result again
Note over DB: Safe only if writes are idempotent
Idempotence: the shield against duplicates
An operation is idempotent if doing it twice has the same effect as doing it once. Setting a customer’s address to a given value is idempotent. Adding ten dollars to a balance is not. Applications that consume Kafka should either be idempotent by design, for example by storing a unique event identifier and ignoring repeats, or should use Kafka’s transactional features where suitable. Chaos experiments on consumers are the fastest way to find the places where this design is missing.
A strong answer to “How do you make a Kafka consumer safe against duplicate processing?” mentions idempotent writes with unique event identifiers, storing the offset in the same transaction as the result when possible, and testing with crash injection between the work and the offset commit.
Connect and stream processing applications
Two families of Kafka applications deserve their own experiments. Kafka Connect workers move data between Kafka and other systems, such as databases. Stop a worker, and the cluster of workers should reassign its connectors and tasks to the others. Check how long data flow pauses, whether the connector resumes from the right position and whether the external system receives duplicates. Also test a failure of the external system itself, such as a database that is unavailable for several minutes, to see if the connector retries, pauses safely or drops records.
Stream processing applications keep local state, such as counts or joins, and back it up to Kafka topics. Kill an instance and watch it rebuild its state on another machine. The rebuild can take long for large state, and during that time results are delayed. Measure this restore time and check that standby copies of the state are configured if the delay is too large. Then repeat with a broker failure during the restore, which is a harder and more realistic case.
12Dependency and Security Chaos
Around every Kafka cluster sits a ring of helpers. When one of them fails, Kafka often fails with it.
Naming and addressing
Clients find brokers by name. Experiments on DNS reveal whether clients survive a name resolving to the wrong address, resolving slowly or not resolving at all. Some teams have discovered that their clients cached a single broker address forever, or that their bootstrap list contained only one broker. Try changing the address of a broker and see whether clients follow. Also test the load balancer in front of brokers, if you use one, because Kafka clients need to reach individual brokers and a misconfigured balancer can hide failures or send clients to the wrong node.
Schema registry and other services
If producers and consumers use a schema registry to encode and decode messages, the registry becomes a dependency on the critical path. Stop it for a few minutes. Well-built clients cache schemas, so existing traffic continues, but new schemas and restarted clients may fail. Find out which of your applications keep running and which stop. The same applies to Kafka Connect workers, stream processing applications, monitoring agents and secret stores that supply credentials.
Certificates and credentials
Expired certificates and rotated passwords are among the most common causes of real Kafka outages, since they arrive on a calendar date and everything fails at once. Test them deliberately: use a certificate that expires in a few minutes, rotate a service account’s password and see which clients reconnect automatically. Check that alerts fire well before expiry and that renewal is automated. If the platform has strict access rules, test that removing a permission by mistake produces a clear error and a fast fix, rather than a mysterious silent failure. The guide on fine-grained ACL design explains how to organize such rules.
Configuration and human error
| Human-error scenario | How to simulate safely | What to learn |
|---|---|---|
| Topic deleted by mistake | Delete a test topic with realistic consumers attached | Whether access rules and process prevent it, and how fast you can recover |
| Wrong setting applied to one broker | Change a non-critical setting on a test broker | Whether configuration drift is detected |
| Bad rolling upgrade | Roll out a known-bad version on a staging cluster | How quickly the team notices and rolls back |
| Permission removed by mistake | Remove one application’s rights in staging | How clear the error is and how fast the cause is found |
| Unplanned partition reassignment during peak | Start a large reassignment without throttling in staging | Effects on latency and how to cancel it |
Think of a city’s power grid. The main power plant matters, but a broken transformer, a cut cable or a missed bill can also turn off the lights on a street. Testing only the power plant tells you little about whether homes stay lit. Kafka’s helpers are the transformers, cables and bills.
Keep a “calendar of expiries”: every certificate, token, license and password that has an end date. Run an experiment once a year that lets a test certificate expire on purpose, so the process is familiar before the real date arrives.
A sample certificate-expiry drill
Prepare a short-lived certificate
Issue a test certificate for one non-critical client that expires in ten minutes.
Predict the outcome
Write down what should happen: an alert first, then automatic renewal, with no failed connections.
Disable automatic renewal for the test client
Simulate the situation where renewal quietly stopped working months ago.
Let it expire
Watch the alerts, the broker logs and the client errors as the moment passes.
Follow the runbook
Have an engineer who did not prepare the test use the documentation to fix it, and time how long it takes.
The most useful measurement is not whether the client failed, since you know it will. It is how many minutes passed before anyone knew, how many before someone understood, and how many before it was fixed.
13Zone Failure and Disaster Recovery Experiments
The biggest promise a cloud architecture makes is that the loss of a whole zone will not stop the business. Prove it.
Rack awareness and zone-level thinking
Kafka can be told which rack, or in the cloud which Availability Zone, each broker lives in. With that knowledge it places the replicas of one partition in different zones. With three zones, a replication factor of three and a minimum ISR of two, losing one full zone should leave every partition with two replicas, still writable with strict acknowledgment. This design is only as good as its execution: a topic created before rack awareness was enabled, or a broker labeled with the wrong zone, silently breaks the guarantee.
Experiment 22: verify replica placement
Before injecting any fault, run a check. For every partition, list which zone each replica lives in and confirm that no partition has two replicas in the same zone. This inspection is itself a valuable experiment, since it often uncovers old topics with poor placement.
Experiment 23: lose a zone
Simulate the loss of one zone by stopping all brokers in it, or by blocking all network traffic to and from that zone. Cloud providers offer services that help; for example, AWS Fault Injection Service can stop instances by tag and can disrupt network connectivity for a subnet, and it supports stop conditions tied to monitoring alarms. Check the latest documentation for the actions available and the safety features. In the experiment, verify that producers and consumers continue, that client failover works when clients also sit in the lost zone, that capacity in the two remaining zones is enough for the whole load and that recovery after the zone returns does not overwhelm the network.
Losing one of three zones removes a third of your brokers. The remaining two-thirds must carry all the traffic plus the recovery work. If your brokers normally run at seventy percent load, they will be overloaded in the drill. Plan for headroom in the design, and test it.
Experiment 24: cluster failover to a second region
Some organizations copy data to a second cluster in another region using a replication tool such as MirrorMaker 2. The copying is asynchronous, so the second cluster lags behind, and a real failover may lose the most recent events. A failover drill tests the whole procedure: stopping producers or switching their addresses, deciding where consumers resume given that offsets differ between clusters, and measuring the amount of data lost or repeated. It also tests the reverse process of returning to the primary region, which is often harder than failing over.
| Measure | Meaning | Question the drill answers |
|---|---|---|
| Recovery time objective (RTO) | How long the service may be unavailable | How long did failover really take, including human decisions? |
| Recovery point objective (RPO) | How much recent data may be lost | How many events were missing on the second cluster? |
| Consumer resume accuracy | Whether consumers restart at the right place | How many events were skipped or repeated after switching? |
| Failback time | How long it takes to return to normal | Can we come back without another outage? |
Managed Kafka services
If you run on a managed service such as Amazon MSK, the provider replaces failed brokers and patches them on a schedule, so some of the experiments above are not under your control. What remains fully testable is the client side and the architecture around the cluster: how your applications behave when brokers restart during maintenance, whether they follow leader changes, and whether your monitoring notices. The service offers an operation to reboot a broker, which can be used as a controlled fault, and the provider’s monitoring metrics can serve as your steady-state signals. Read the current documentation to see which faults are allowed.
Follower fetching and cross-zone traffic
By default, consumers read from the leader of each partition, and the leader may be in a different zone from the consumer. This creates cross-zone network traffic, which in many clouds is billed and adds latency. Newer Kafka versions let consumers read from a nearby follower if the client announces its zone. A related experiment is to disrupt a zone and observe where consumers read from. It shows whether the design keeps traffic local in normal times and switches cleanly during a failure, and whether the cost savings of local reads cost you anything in freshness, since followers can be slightly behind the leader.
14Verifying Data Integrity Under Chaos
Staying up is not enough. After every experiment, prove that no data was lost, duplicated or reordered.
The three integrity questions
Did any acknowledged message disappear?
If the producer received confirmation, the message must be readable afterwards. Any gap is a serious finding.
Did any message appear twice?
Duplicates are expected with at-least-once delivery, but the count should be understood and harmless.
Did messages for a key stay in order?
Order inside a partition should be preserved, even across retries and leader changes.
A verification harness
Build a small test program that plays the role of a strict auditor. The writer part sends a stream of messages, each containing a key, an increasing sequence number and a checksum, and it records every message that Kafka acknowledged. The reader part reads the topic from the beginning after the experiment and checks three things: every acknowledged sequence number is present, the numbers for each key increase without going backward, and the number of repeats is counted. The comparison result is a clear verdict on data integrity. Testing tools for distributed systems use this same idea, and independent researchers have used similar checks to study Kafka’s behavior in the past.
flowchart LR
W["Writer: numbered messages with keys and checksums"] --> K[("Kafka topic under test")]
W --> L["Ledger of acknowledged messages"]
X["Chaos tool injects faults"] --> K
K --> R["Reader after the experiment"]
R --> V{"Compare with ledger"}
L --> V
V --> O1["Missing messages: loss"]
V --> O2["Repeated messages: duplicates"]
V --> O3["Out-of-order per key: ordering breaks"]
V --> O4["All clear: integrity holds"]
What counts as a failure?
| Finding | Acceptable? | Typical cause |
|---|---|---|
| Acknowledged message missing | No, in a system configured for durability | Weak acknowledgment or minimum ISR setting, unclean leader election, disk loss without replicas |
| Message missing that was never acknowledged | Yes, the producer knew and should have retried | Error handling in the application decides the outcome |
| Duplicates after a client crash | Yes, if downstream systems tolerate them | At-least-once delivery, retries without idempotence |
| Out-of-order events for one key | No, unless the application explicitly accepts it | Retries with multiple in-flight requests and no idempotence |
| Gaps after consumer downtime longer than retention | No, but predictable | Lag alerts too late, retention too short |
Keep the auditor running permanently against a dedicated topic in each environment, even between experiments. Then any integrity problem, including those caused by real failures nobody planned, shows up as a failed check.
Running the auditor cheaply
The integrity auditor does not have to be complex. A few hundred lines of code and a small dedicated topic are enough to begin with. The writer should use several keys so that ordering can be checked in many partitions, and it should write at a modest, steady rate so the results are easy to interpret. The reader should store what it saw in a simple file or table, so the comparison can be repeated later. Add a summary at the end that prints counts of missing, repeated and out-of-order messages. Start small, and extend it when the experiments demand it, for example with transactions or with several topics.
15Tooling: Choosing How to Inject Faults
You do not need an expensive platform to start. But it helps to know what kinds of tools exist and what each one is good at.
| Tool or approach | What it does | Good for | Caution |
|---|---|---|---|
| Operating system commands | Stop processes, block ports with firewall rules, add delay and loss with traffic control features | Simple, transparent experiments on virtual machines | Manual cleanup; easy to forget to undo |
| Stress tools | Consume processor, memory or disk input and output on demand | Resource exhaustion faults | Can affect neighbors on shared hosts |
| Network proxies such as Toxiproxy | Sit between client and server and add latency, cut connections, limit bandwidth | Client-side and integration tests | Requires routing traffic through the proxy |
| Trogdor (from the Kafka project) | A test framework that can run workloads and inject faults such as process stops and network partitions | Kafka-specific testing in lab clusters | Set-up effort; used mainly by Kafka developers |
| Kubernetes chaos tools such as Chaos Mesh and LitmusChaos | Kill pods, delay or drop network traffic, stress containers, disturb files and clocks | Kafka on Kubernetes, including operator-managed clusters | Powerful permissions; restrict namespaces and use approvals |
| Cloud fault injection services such as AWS Fault Injection Service | Stop or reboot instances, disrupt network connectivity, pause volume input and output, with stop conditions from alarms | Cloud-hosted brokers and clients | Check the supported actions and required roles; not all managed services are targets |
| Commercial chaos platforms | Guided experiments, safety controls, reporting | Organizations that want a managed programme | Cost; still needs Kafka-specific hypotheses |
| Kafka monitor or canary tools | Measure end-to-end latency and availability continuously | Steady-state signal | A tool alone does not decide what to test |
A reference architecture
flowchart TB
PLAN["Experiment card in Git"] --> CTRL["Chaos controller with approvals"]
CTRL --> AGENT["Fault agents on hosts, pods or cloud APIs"]
AGENT --> TARGET["Kafka brokers, controllers, clients, network"]
TARGET --> METRICS["Metrics and logs"]
CANARY["Canary producer and consumer"] --> METRICS
AUDIT["Integrity auditor"] --> METRICS
METRICS --> ALARM["Abort alarms"]
ALARM -->|breach| CTRL
METRICS --> DASH["Dashboards and reports"]
DASH --> REVIEW["Review meeting and follow-up tickets"]
Kafka on Kubernetes: extra points
Operator-managed Kafka on Kubernetes adds its own behaviors. Pods that are killed are recreated by the platform, and the operator may perform its own rolling restarts. Chaos experiments here should also check the pod disruption budget, which limits how many brokers may be down at once, the spread of pods across nodes and zones, the behavior of persistent volumes when a pod moves and the effect of node drains. A frequent finding is that pods of one Kafka cluster land on the same node or zone because no spreading rule was set, so the replication factor gives less protection than expected.
Your first experiments can use nothing more than a shell, a stopwatch and a dashboard. Introduce tools when the manual steps become repetitive. The value lies in the questions and measurements, not in the software.
Build, adopt or buy?
Teams often ask whether to write their own chaos scripts, adopt an open-source tool or buy a platform. A practical rule is to start with what you already have. Shell scripts and cloud command-line tools are enough for the first ten experiments. Adopt an open-source or cloud-native tool when you need repeatability, scheduling, stop conditions and audit trails. Consider a commercial platform when you want many teams to run experiments safely with central reporting. Whatever you pick, the same rules apply: hypotheses, small radius, measured results and follow-up.
| Team situation | Reasonable starting choice |
|---|---|
| Small team, self-managed brokers on virtual machines | Scripts using operating system tools, plus a canary |
| Kafka on Kubernetes | An open-source Kubernetes chaos tool with restricted namespaces |
| Heavy use of one cloud provider | That provider’s fault injection service with alarms as stop conditions |
| Many teams and strict compliance needs | A managed platform or an internal service that adds approvals and reports |
16Running a Game Day, Step by Step
A game day is a planned event where people and systems are tested together. It is the best way to begin.
Roles
Experiment lead
Owns the plan, runs the steps and calls the stop if needed.
Incident commander
Practices leading the response as if the failure were real, without knowing every detail of the plan.
Observers
Watch dashboards and application behavior and record what they see with times.
Scribe
Writes a timeline of events, decisions and surprises in a shared document.
The schedule
Briefing (15 minutes)
Review the experiment card, scope, abort rules, communication channels and roles. Confirm everyone knows how to stop.
Steady-state check (10 minutes)
Confirm dashboards are healthy, the canary is smooth and there are no other changes in flight.
Inject the fault
The experiment lead starts the fault at a stated time and announces it in the channel.
Observe and respond
Observers call out what they see. The incident commander leads the response as if it were real, using the actual runbook and tools.
Stop and restore
At the end of the planned time, or at an abort trigger, the fault is removed and the recovery is watched to the end.
Verify integrity
Run the data auditor and compare results with the hypothesis.
Debrief
Within a day, hold a blameless review: what did we predict, what happened, what surprised us and what will we change?
Blameless culture
People will only report surprises honestly if they are sure they will not be punished for them. The purpose of an experiment is to find weaknesses in the system, not in the people who built it. Praise the team that finds a flaw. A game day that ends with everyone saying “nothing went wrong” should make you suspicious that the experiment was too gentle or that observers missed something.
Surprise mode, later
Once the team is comfortable, you can run experiments where the response team does not know the exact fault in advance, as in a fire drill. This tests the alerting and the diagnosing skills that a real incident demands. Only do this after the standard game days have removed the obvious weaknesses, and always with a hidden safety person who can stop everything.
Example: a first game day for a payments platform
A team invites the application owners, the platform engineers and the on-call lead to a two-hour session on the pre-production cluster. They stop one broker and watch. Producers recover in 12 seconds, but a downstream service crashes because it treats a temporary error as fatal. Two alerts fire, but the runbook link in one of them is out of date. The team leaves with three tickets, and the next game day a month later shows the crash and the broken link both fixed.
What observers should prepare
One dashboard per observer
Give each observer a single focus, such as producers, consumers, brokers or alerts, so nothing is missed.
Shared time
Everyone writes times in the same zone and, if possible, from the same clock, so the timeline can be reconstructed.
Write what you see, not what you think
Record facts with times. Interpretation comes in the debrief.
Capture the graphs
Save images of key charts at the start, peak and recovery for the report.
17Automating Chaos and Growing the Practice
A single game day proves a moment in time. Automation keeps proving the system as it changes.
A maturity ladder
flowchart LR
L0["Level 0: no experiments, hope only"] --> L1["Level 1: manual game days in staging"]
L1 --> L2["Level 2: scripted experiments in staging, run before releases"]
L2 --> L3["Level 3: scheduled experiments in production with guard rails"]
L3 --> L4["Level 4: continuous, automated, part of every change"]
| Level | What you have | Next step |
|---|---|---|
| 0 | Diagrams, replication settings and belief | Define steady state and build a canary |
| 1 | Occasional manual drills with a written card and debrief | Script the most valuable experiments |
| 2 | Experiments run by scripts on a schedule or before releases in staging | Add automatic abort rules and reports |
| 3 | Small, safe experiments in production during working hours with alarms as stop conditions | Cover more fault types and more services |
| 4 | Experiments triggered by changes, results as release gates, ownership by service teams | Keep the library relevant as systems evolve |
Put experiments into the delivery pipeline
Once experiments are scripted, they can become part of the process for changing Kafka. Before a rolling upgrade of brokers, run the broker-stop experiment on a staging cluster with the new version. Before changing a producer library, run the producer crash test against the new build. Before enabling encryption, test the impact under load and failure. A pass becomes a required gate, and a failure blocks the release until fixed.
Build a library of experiments
Store every experiment card and script in a repository, with clear names and versions. Tag them by fault type, scope and risk level, and record their history: when they ran, results, and links to follow-up work. Over time this library becomes an accurate map of what your platform has survived. It is also a training resource for new engineers, who learn a lot by reading how each failure was expected to behave.
Measure the programme itself
Experiments run per quarter
Shows whether the habit is real.
Weaknesses found and fixed
Shows that the practice produces value, not just activity.
Time to detect and to recover
Should improve across repeated experiments.
Coverage of the dependency map
The share of critical arrows that have been tested in the last year.
Give each experiment an owner in the team that owns the service. Central platform teams can provide tools and coaching, but the people who build the service are the ones who must learn from the result and fix it.
Guard rails for continuous experiments in production
Only during business hours
Run when engineers are present and awake, never in the middle of the night.
Only when healthy
The scheduler checks steady state and skips the run if anything is already degraded.
Never during change freezes or incidents
A calendar of freezes and an incident flag block all experiments automatically.
One fault at a time
Only a single experiment may run in a cluster, so results remain clear.
18Reading Results and Turning Them Into Fixes
The experiment is only half the work. The other half is understanding the result and changing something.
Three kinds of outcome
Every experiment ends in one of three ways. In a pass, the system stayed within limits, and you record the timings as a new baseline. In a fail with insight, the system missed the hypothesis and you now know why. In a blind result, you could not tell what happened because of missing monitoring, and the first fix is better observability. All three are valuable. Passing many times in a row is not a reason to stop, but a reason to raise the difficulty.
Findings that appear again and again
| Common finding | What it means | Usual fix |
|---|---|---|
| Minimum ISR is one on important topics | Acknowledged writes can sit on a single copy | Raise to two with a replication factor of three, and update producers to handle rejections |
| Clients give up during failover | Delivery timeout or retry limit shorter than real recovery time | Set timeouts from measured failover times and add back-off |
| Replicas share a zone or rack | Rack awareness missing or wrong | Set zone labels, reassign old topics, add placement checks |
| Consumers double-count after crashes | Processing is not idempotent | Add unique event identifiers or use transactions |
| Rebalance storms after restarts | Poor group settings or simultaneous restarts | Use cooperative rebalancing, static membership and staggered restarts |
| Alert never fired or went to nobody | Alert rules, routing or contact lists are wrong | Test alerts as part of every experiment |
| Runbook is outdated | Cluster changed, document did not | Attach the runbook to the experiment card and update after each run |
| Recovery traffic overwhelms the network | No throttle on catch-up replication | Set replication throttles and capacity headroom |
| Single dependency stops everything | Registry, DNS or secret store without redundancy | Add caching, redundancy and timeouts |
| Slow node not noticed | Monitoring shows usage but not latency | Add latency-based alerts and automated leader draining |
Write the result in plain words
A good report is short. It restates the hypothesis, shows a graph of steady-state measures across the run, lists the timeline of key events, records the measured numbers and ends with a list of actions with owners and dates. Send it to the teams that were affected and add it to the library. A report that nobody reads teaches nobody anything.
Re-run after fixing
A fix is a hypothesis too. After the change, run the same experiment again to confirm that the weakness is gone. Teams that skip this step often find later that the fix was incomplete, or that it created a new problem.
Do not “fix” a failed experiment by making the experiment gentler. If a hypothesis fails, the system needs to change, not the test. Relax a hypothesis only if the requirement itself was unrealistic, and record the decision and the reason.
A simple debrief template
| Question | What to write down |
|---|---|
| What did we expect? | The hypothesis, with numbers |
| What actually happened? | The timeline and measured values |
| What surprised us? | Any behavior nobody predicted, good or bad |
| Did monitoring show it clearly? | Missing or misleading graphs and alerts |
| Did people know what to do? | Gaps in the runbook, access or knowledge |
| What will we change? | Actions with an owner and a due date |
| When will we test again? | Date of the follow-up experiment |
Keep the debrief blameless and short. The value is in the list of actions and in the promise to test again, not in the length of the meeting.
19Trade-offs, Patterns, Anti-patterns and Best Practices
Chaos engineering costs time, tools and a little risk. Weigh them honestly.
Benefits of chaos engineering for Kafka
- Finds hidden weaknesses before customers do.
- Produces measured failover, detection and recovery times.
- Builds team confidence and practiced responses.
- Keeps runbooks, alerts and documentation honest.
- Prevents drift in settings that quietly reduce durability.
Costs and risks
- Time to design, run and analyze experiments.
- Risk of real customer impact if blast radius is not controlled.
- Effort to build monitoring good enough to see the results.
- Cultural resistance from teams that fear blame.
- Tools with strong permissions become security risks.
Patterns that work
Steady state first
Build the canary and the dashboard before any fault.
Small radius, then grow
Move through the rings from staging to production step by step.
Automatic abort
Alarms that remove the fault without waiting for a human.
Integrity auditor
Always verify loss, duplicates and order after a run.
Experiments as code
Versioned cards and scripts in a repository, reviewed like software.
Blameless debriefs
Every run ends with learning and named follow-ups.
What people do
They run a dramatic experiment in production, such as killing several brokers at once, as their very first chaos test, with no steady-state measures and no stop rule.
Why it hurts
If something goes wrong, customers suffer and nobody can tell whether the cause was the fault or something else. Leaders then ban all future experiments, and the organization loses a useful tool.
What to do instead
Begin in a safe environment with a small fault, measured steady state and a written stop rule. Earn the right to go bigger.
What people do
They treat chaos engineering as a tool purchase and run random fault schedules without hypotheses, then present the graphs as evidence of resilience.
Why it hurts
Without a prediction and a limit, there is no way to say pass or fail. The activity looks impressive but teaches little, and real weaknesses remain hidden.
What to do instead
Write a hypothesis with measures, limits and times for every experiment, and decide beforehand what you will change if it fails.
Common mistakes checklist
- Skipping the steady-state check and running on an already unhealthy cluster.
- Testing only brokers and forgetting clients, dependencies and people.
- Using irreversible faults when a reversible one would answer the question.
- Leaving a fault active after the experiment ends.
- Not verifying data integrity after the run.
- Making the test gentler after a failure instead of fixing the system.
- Running experiments once and never repeating them as the system changes.
- Giving the chaos tool broad permissions with no logging or approvals.
Best practices in one place
Know your steady state and build a canary. Write hypotheses with numbers. Keep the blast radius small and grow it in rings. Arm abort rules before injecting anything. Prove data integrity after every run. Cover clients and dependencies, not only brokers. Turn every finding into a ticket with an owner and re-run the experiment after the fix. Automate what works, and keep the human game day for learning how people respond.
20Real-World Usage Patterns
Chaos engineering grew out of large streaming and internet companies, and the same ideas now serve many industries.
The origin at Netflix
Netflix developed Chaos Monkey to make sure every service could survive losing a virtual machine at any time, and it later grew a family of tools for larger failures. Their event pipelines, which move enormous volumes of data between services, were built with the same mindset: components are expected to fail, and the system is expected to carry on. The lesson for Kafka teams is cultural. Resilience is a feature that must be exercised regularly, not a property that is assumed.
Continuous end-to-end monitoring at a Kafka pioneer
LinkedIn, where Kafka was created, built a monitoring framework that continuously sends test messages through clusters and reports latency and availability. It is now available as an open-source project. Teams use this type of always-on canary as the steady-state signal in their chaos experiments, and as an alarm in daily operation.
The regulated financial firm
A bank running Kafka for payment events must show regulators that it can survive the loss of a data centre zone. It runs planned zone-loss drills twice a year, measures recovery time and data loss against its stated objectives, keeps the reports as evidence and repeats the drill after every major architectural change. Smaller monthly experiments cover broker loss, network delay and certificate expiry.
The retailer before its busiest season
An online retailer schedules a series of game days each autumn before the holiday shopping rush. They stop brokers, slow networks and kill consumers under load-test traffic. In one run they discover that the order-processing consumers double-count when killed at a certain moment. They fix the idempotence problem months before the peak, avoiding what would have been a costly error during their biggest sales days.
Managed Kafka on AWS
A team using Amazon MSK cannot stop the provider’s brokers at will, so it focuses on the parts it controls. It uses AWS Fault Injection Service or simple scripts to disturb its client fleet, adds network latency between application subnets and the cluster, and triggers broker reboots where the service allows. It watches the service’s CloudWatch metrics and its own canary, and it uses alarms as stop conditions. The experiments reveal that several applications had delivery timeouts shorter than the service’s normal maintenance restart, and those settings are corrected before the next patching window.
Lessons that repeat
Teams that benefit most share a few habits. They measure before they break. They pick faults that resemble real events. They include the human response in the drill. They act on every finding and re-run to confirm the fix. And they see chaos engineering not as a project with an end date but as a routine, like testing the fire alarm every month.
21Frequently Asked Questions
22Summary and Key Takeaways
What to remember
- Chaos engineering is science, not sabotage: define steady state, form a hypothesis, inject a realistic fault with a small blast radius, observe, and improve.
- Test the whole chain: brokers, controllers, network, disks, clients, dependencies, certificates, people and runbooks all matter, and the weakest untested link decides your real availability.
- Build the measuring tools first: a canary producer and consumer, clear service level objectives and an integrity auditor turn vague feelings into pass or fail results.
- Prove the promises with the right settings: replication factor, minimum in-sync replicas, acknowledgment mode, unclean leader election, rack awareness and client timeouts are the usual sources of surprise.
- Control the blast radius: move through rings from a throwaway cluster to production, write abort rules, use alarms as stop conditions and prefer reversible faults.
- Run game days with people, not only machines: practice the response, keep debriefs blameless and turn every finding into an owned, dated action, then re-run the experiment.
- Automate and repeat: keep experiments as code, add them to release pipelines and measure the programme, because a system that changes weekly needs proof that renews.