Home DevOps Amazon MSK: Managed Kafka Streaming — Production Patterns That Don't Fail at 3 AM
Advanced 3 min · July 18, 2026

Amazon MSK: Managed Kafka Streaming — Production Patterns That Don't Fail at 3 AM

Amazon MSK deep dive: avoid common pitfalls, tune for throughput, and handle failures in production Kafka clusters on AWS..

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Everything here is grounded in real deployments.

Follow
Production
production tested
July 18, 2026
last updated
2,466
articles · all by Naren
Before you start⏱ 30 min
  • Apache Kafka fundamentals (topics, partitions, consumer groups)
  • AWS networking basics (VPC, subnets, security groups)
  • Experience with distributed systems and at-least-once semantics
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer

Amazon MSK is AWS's managed Kafka service. You create a cluster, configure topics, and connect producers/consumers — AWS handles broker health and ZooKeeper. But you must still tune for throughput, handle rebalances, and monitor lag yourself.

✦ Definition~90s read
What is Amazon MSK?

Amazon MSK (Managed Streaming for Apache Kafka) is a fully managed Kafka service on AWS. It handles broker provisioning, ZooKeeper management, and automatic recovery, but you still own topic configuration, client tuning, and failure handling.

Think of Amazon MSK as a valet parking service for your Kafka cluster.
Plain-English First

Think of Amazon MSK as a valet parking service for your Kafka cluster. You hand over the keys (your data streams), and they park the car (manage brokers and ZooKeeper). But you still decide how fast to drive (producer/consumer config), which route to take (topic partitioning), and what to do if the car breaks down (failure handling).

You've seen it. A Kafka cluster that was humming along at 10k messages/sec suddenly starts throwing connection timeouts at 2 AM. The pager goes off. You SSH in, see broker logs full of 'Not enough replicas', and realize your MSK cluster just silently dropped a broker. The managed part doesn't mean bulletproof. Amazon MSK handles the infrastructure — but your application code and topic design are still on you. This article walks through the production patterns that keep your Kafka pipeline alive when everything else is on fire. By the end, you'll know how to configure MSK for high throughput, handle rebalances without data loss, and debug the failure modes that actually happen.

Why MSK Isn't Magic — The Shared Responsibility Model

Amazon MSK manages the ZooKeeper ensemble and broker lifecycle. But you own the Kafka configuration, topic design, client tuning, and monitoring. The classic mistake is treating MSK like a fully managed black box. It's not. When a broker fails, MSK replaces it — but the new broker has no data. It must replicate from the remaining brokers. During that window, your min.insync.replicas setting can block producers. I've seen a payments pipeline stall for 20 minutes because someone set min.insync.replicas=3 on a 3-broker cluster. One broker went down, and no producer could write. The fix: always set min.insync.replicas to 2 on a 3-broker cluster, or use acks=1 for latency-sensitive workloads.

msk-topic-config.shDEVOPS
1
2
3
4
5
6
7
8
9
10
11
12
// io.thecodeforge — DevOps tutorial

# Create a topic with safe defaults for production
kafka-topics.sh --create \
  --bootstrap-server $MSK_BROKER_STRING \
  --replication-factor 3 \
  --partitions 6 \
  --config min.insync.replicas=2 \
  --config retention.ms=604800000 \
  --config retention.bytes=53687091200 \
  --config cleanup.policy=delete \
  --topic orders
Output
Created topic orders.
⚠ Production Trap: min.insync.replicas = replication factor
If you set min.insync.replicas equal to replication.factor, a single broker failure will block all writes. Always leave at least one broker of slack.

Tuning Producers for Throughput Without Losing Data

The default producer config is safe but slow. For high-throughput pipelines, you need to tune batch.size, linger.ms, and compression.type. The goal is to batch more messages per request without increasing latency beyond your SLA. Start with batch.size=65536 (64 KB) and linger.ms=10. Use snappy compression — it's fast and reduces network I/O. But here's the gotcha: if your producer is sending messages to many partitions, batching becomes less effective because each partition gets its own batch. The fix: ensure your partition count is reasonable (e.g., 6-12 per broker) and use a sticky partitioner to batch more messages to the same partition.

OrderProducer.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// io.thecodeforge — DevOps tutorial

import org.apache.kafka.clients.producer.*;
import java.util.Properties;

public class OrderProducer {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put("bootstrap.servers", System.getenv("MSK_BROKER_STRING"));
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        // High throughput settings
        props.put("batch.size", 65536);       // 64 KB batches
        props.put("linger.ms", 10);            // Wait up to 10ms for more messages
        props.put("compression.type", "snappy");
        props.put("acks", "1");               // Leader ack only — faster, safe with min.insync.replicas=2
        props.put("max.in.flight.requests.per.connection", 5);
        props.put("retries", 3);
        props.put("enable.idempotence", true); // Prevent duplicates on retry

        KafkaProducer<String, String> producer = new KafkaProducer<>(props);
        // Send orders
        for (int i = 0; i < 1000; i++) {
            producer.send(new ProducerRecord<>("orders", "order-" + i, "{\"id\":" + i + "}"));
        }
        producer.close();
    }
}
Output
(No output — messages sent asynchronously)
💡Senior Shortcut: Enable idempotence for exactly-once semantics
Set enable.idempotence=true and acks=all for critical data. The performance cost is negligible with batching.

Consumer Design: Avoiding the Rebalance Storm

Consumer rebalances are the #1 cause of production Kafka outages. When a consumer joins or leaves the group, all consumers stop processing and re-assign partitions. If your session.timeout.ms is too low (default 10s), a slow GC pause or network hiccup triggers a rebalance. I've seen a 50-consumer group rebalance every 30 seconds because of a misconfigured heartbeat interval. The fix: set session.timeout.ms to 45s and heartbeat.interval.ms to 15s. Also use cooperative rebalancing (partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor) to reduce the number of full rebalances.

OrderConsumer.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// io.thecodeforge — DevOps tutorial

import org.apache.kafka.clients.consumer.*;
import java.time.Duration;
import java.util.Properties;
import java.util.List;

public class OrderConsumer {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put("bootstrap.servers", System.getenv("MSK_BROKER_STRING"));
        props.put("group.id", "order-processors");
        props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        // Stable consumer settings
        props.put("session.timeout.ms", 45000);
        props.put("heartbeat.interval.ms", 15000);
        props.put("max.poll.interval.ms", 300000);  // 5 min to process a batch
        props.put("max.poll.records", 500);
        props.put("partition.assignment.strategy", "org.apache.kafka.clients.consumer.CooperativeStickyAssignor");
        props.put("enable.auto.commit", false);  // Manual commit for control

        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
        consumer.subscribe(List.of("orders"));

        try {
            while (true) {
                ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
                for (ConsumerRecord<String, String> record : records) {
                    processOrder(record.value());
                }
                consumer.commitSync();  // Commit after successful batch
            }
        } finally {
            consumer.close();
        }
    }

    private static void processOrder(String orderJson) {
        // Simulate processing
        System.out.println("Processing: " + orderJson);
    }
}
Output
Processing: {"id":0}
Processing: {"id":1}
...
⚠ The Classic Bug: Auto-commit with slow processing
If you use enable.auto.commit=true and your consumer crashes after processing but before the next poll, you'll lose messages. Always commit manually after processing.

Monitoring MSK: What AWS Doesn't Tell You

MSK exposes CloudWatch metrics, but the defaults are useless. You need to enable per-broker metrics and set alarms on KafkaDataLogsDiskUsed, CpuUser, and NetworkIn/Out. The critical metric that everyone misses: EstimatedMaxTimeLag. This tells you how far behind the slowest consumer is. Set an alarm at 10 minutes. Also monitor UnderReplicatedPartitions — if it stays above 0 for more than 5 minutes, a broker is struggling. I've seen teams miss a broker failure because they only monitored average metrics. Always look at the max across brokers.

msk-cloudwatch-alarms.shDEVOPS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// io.thecodeforge — DevOps tutorial

# Create CloudWatch alarm for broker disk usage
aws cloudwatch put-metric-alarm \
  --alarm-name MSK-HighDiskUsage \
  --alarm-description "Alert when broker disk usage exceeds 80%" \
  --metric-name KafkaDataLogsDiskUsed \
  --namespace AWS/Kafka \
  --statistic Maximum \
  --period 300 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --dimensions Name=Cluster Name,Value=my-msk-cluster \
  --evaluation-periods 2 \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:MyTopic
Output
(Alarm created)
🔥Interview Gold: How does MSK handle broker failure?
MSK detects broker failure via ZooKeeper, replaces the instance, and re-attaches the EBS volume. The new broker catches up via replication. During this time, partitions with only one replica become unavailable for writes if min.insync.replicas is not met.

Scaling MSK: Adding Brokers Without Downtime

You can add brokers to an MSK cluster, but it's not instantaneous. The process takes 15-30 minutes and triggers a rolling restart. During this time, clients may experience temporary disconnects. The trick: use a bootstrap string that includes all broker DNS names, and configure your clients with metadata.max.age.ms to refresh metadata every 5 minutes. Also, never scale down — MSK doesn't support it. If you need to reduce capacity, create a new cluster and migrate.

msk-scale-up.shDEVOPS
1
2
3
4
5
6
7
8
9
10
11
// io.thecodeforge — DevOps tutorial

# Update MSK cluster to increase number of brokers
aws kafka update-broker-count \
  --cluster-arn arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abcd1234 \
  --target-number-of-broker-nodes 6

# Wait for update to complete (check status)
aws kafka describe-cluster \
  --cluster-arn arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abcd1234 \
  --query 'ClusterInfo.State'
Output
UPDATING
...
ACTIVE
⚠ Never Do This: Scale down MSK
MSK does not support decreasing the number of brokers. You must create a new cluster and migrate. Plan your capacity upfront.

When Not to Use MSK — The Honest Take

MSK is overkill for low-throughput workloads (< 1 MB/s). Use Amazon SQS or Kinesis instead — they're simpler and cheaper. Also, if you need custom Kafka versions or plugins, MSK's version lock-in (only supports certain versions) will frustrate you. For teams that need full control, self-hosted Kafka on EC2 is still viable. But for most production pipelines, MSK's operational savings outweigh the limitations.

🔥Senior Shortcut: When to choose MSK over self-hosted
If your team has fewer than 2 dedicated Kafka ops engineers, use MSK. The cost of a pager rotation for broker failures is higher than the MSK premium.
● Production incidentPOST-MORTEMseverity: high

The Silent Broker Drop That Killed Our Pipeline

Symptom
Producers started getting NotEnoughReplicasException and consumers saw lag spike to millions. No alerts from MSK health checks.
Assumption
We assumed a network partition or AWS AZ failure.
Root cause
A broker ran out of disk space due to retention policy misconfiguration. MSK auto-replaced the broker, but the new broker took 15 minutes to catch up, during which min.insync.replicas was not met.
Fix
Set retention.bytes per topic to a safe limit (e.g., 50 GB) and enabled log.retention.bytes on the cluster. Also increased min.insync.replicas to 2 and default.replication.factor to 3.
Key lesson
  • Never assume MSK's auto-recovery is instant.
  • Always design for temporary broker unavailability with proper acks and replication settings.
Production debug guideSystematic recovery paths for the failure modes engineers actually hit.3 entries
Symptom · 01
Producers get NotEnoughReplicasException
Fix
1. Check min.insync.replicas config on the topic. 2. Verify number of in-sync replicas with kafka-topics.sh --describe. 3. If a broker is down, wait for MSK to replace it (15-30 min). 4. Temporarily reduce min.insync.replicas to 1 if urgent.
Symptom · 02
Consumer lag growing despite idle consumers
Fix
1. Check consumer group status with kafka-consumer-groups.sh --describe --group <group>. 2. Look for Stable state — if Rebalancing, fix session timeouts. 3. Increase partitions or add more consumers. 4. Check processing logic for blocking calls.
Symptom · 03
High CPU on all brokers
Fix
1. Check CpuUser CloudWatch metric. 2. Identify heavy topics with kafka-topics.sh --describe. 3. Increase partitions to distribute load. 4. Tune producer batch size and compression. 5. Consider adding brokers.
★ Amazon MSK: Managed Kafka Streaming Triage Cheat SheetFirst-response commands for when things go wrong — copy-paste ready.
Producers timing out with `Request timed out`
Immediate action
Check broker CPU and network bandwidth.
Commands
aws cloudwatch get-metric-statistics --namespace AWS/Kafka --metric-name CpuUser --dimensions Name=Cluster Name,Value=my-cluster --statistics Maximum --period 60 --start-time $(date -u -d '-5 minutes' +%Y-%m-%dT%H:%M:%SZ)
kafka-topics.sh --bootstrap-server $BROKER --describe --topic orders
Fix now
Increase batch.size to 65536 and linger.ms to 10. Set acks=1.
Consumers stuck in rebalance loop+
Immediate action
Check consumer group state.
Commands
kafka-consumer-groups.sh --bootstrap-server $BROKER --group order-processors --describe
Check `session.timeout.ms` and `heartbeat.interval.ms` in consumer config.
Fix now
Set session.timeout.ms=45000, heartbeat.interval.ms=15000, and use CooperativeStickyAssignor.
UnderReplicatedPartitions > 0 for more than 5 minutes+
Immediate action
Check broker health.
Commands
aws cloudwatch get-metric-statistics --namespace AWS/Kafka --metric-name UnderReplicatedPartitions --dimensions Name=Cluster Name,Value=my-cluster --statistics Maximum --period 60 --start-time $(date -u -d '-10 minutes' +%Y-%m-%dT%H:%M:%SZ)
kafka-topics.sh --bootstrap-server $BROKER --describe --under-replicated-partitions
Fix now
Wait for MSK auto-recovery. If persistent, increase replication factor or add brokers.
Disk usage > 80% on a broker+
Immediate action
Check retention settings.
Commands
kafka-configs.sh --bootstrap-server $BROKER --entity-type topics --entity-name orders --describe
Check `retention.bytes` and `retention.ms`.
Fix now
Reduce retention.bytes to 50GB or lower. Increase retention.ms if needed.
FeatureAmazon MSKSelf-Hosted Kafka on EC2
Broker managementFully managedManual (auto-scaling groups, health checks)
ZooKeeperManagedManual (separate cluster or containers)
Version upgradesLimited to MSK-supported versionsFull control
CostPremium over EC2 + EBSEC2 + EBS only
ScalingAdd brokers only (no scale down)Add/remove brokers freely
MonitoringCloudWatch metrics (basic)Full access to JMX, Prometheus, etc.
⚙ Quick Reference
5 commands from this guide
FileCommand / CodePurpose
msk-topic-config.shkafka-topics.sh --create \Why MSK Isn't Magic
OrderProducer.javapublic class OrderProducer {Tuning Producers for Throughput Without Losing Data
OrderConsumer.javapublic class OrderConsumer {Consumer Design
msk-cloudwatch-alarms.shaws cloudwatch put-metric-alarm \Monitoring MSK
msk-scale-up.shaws kafka update-broker-count \Scaling MSK

Key takeaways

1
MSK manages brokers and ZooKeeper, but you own topic config, client tuning, and failure handling
never treat it as a black box.
2
Set min.insync.replicas to replication factor minus 1 to avoid write unavailability during broker failures.
3
Consumer rebalances are the #1 cause of outages
use cooperative rebalancing and tune session timeouts to 45s.
4
Monitor EstimatedMaxTimeLag and UnderReplicatedPartitions
not just average broker metrics.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
How does Amazon MSK handle a broker failure, and what impact does it hav...
Q02SENIOR
When would you choose Amazon MSK over self-hosted Kafka on EC2 in a prod...
Q03SENIOR
What happens when you set `min.insync.replicas` equal to `replication.fa...
Q04JUNIOR
What is the purpose of the `session.timeout.ms` configuration in Kafka c...
Q05SENIOR
You notice consumer lag growing despite the consumers appearing idle. Ho...
Q06SENIOR
How would you design a Kafka pipeline on MSK that handles 100k messages/...
Q01 of 06SENIOR

How does Amazon MSK handle a broker failure, and what impact does it have on producers and consumers?

ANSWER
MSK detects failure via ZooKeeper, replaces the broker instance, and re-attaches the EBS volume. The new broker catches up via replication. During this window, partitions with only one in-sync replica become unavailable for writes if min.insync.replicas is not met. Consumers may experience increased latency as they wait for the new broker to catch up.
FAQ · 4 QUESTIONS

Frequently Asked Questions

01
How do I connect to Amazon MSK from an EC2 instance?
02
What's the difference between Amazon MSK and Amazon Kinesis?
03
How do I monitor consumer lag in Amazon MSK?
04
Can I downgrade the number of brokers in an MSK cluster?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Everything here is grounded in real deployments.

Follow
Verified
production tested
July 18, 2026
last updated
2,466
articles · all by Naren
🔥

That's AWS. Mark it forged?

3 min read · try the examples if you haven't

Previous
AWS Amplify: Full-Stack App Development
47 / 63 · AWS
Next
Amazon DocumentDB: MongoDB-Compatible Document Database