Labs
Each lab takes under an hour on a laptop and turns a claim from this mechanism into a number you measured yourself.
- 1
Head-of-line blocking: log versus queue
Simulate 12 partitions with 100 records/s each and one poison record.
SimulatePython - 2
Per-record calls versus batches: find the natural batch size
Send 100,000 records to a local HTTP server in batches of 1 to 10,000 and fit the fixed cost per call.
MeasurePython with requests - 3
Ack before or after processing: loss versus duplicates
Kill a consumer at random moments: saving the offset first loses records, processing first duplicates them.
Break itPython - 4
Bufferbloat: a bigger buffer buys latency, not throughput
A producer 20% faster than its consumer, with queues from 100 to 100,000: throughput stays put, latency grows with the queue.
SimulatePython - 5
What an overflowing buffer loses
A keyed stream overloads a bounded buffer under drop-newest, drop-oldest and drop-oldest per key: count the records dropped and the entities left with a wrong value.
SimulatePython - 6
Batch size: find the knee
Insert 200,000 rows into SQLite with one commit per batch, then bound trickle-traffic latency with a size-or-age rule.
MeasurePython - 7
Token bucket versus fixed window
Two bursts straddling a one-second boundary against a fixed window, two token buckets and a sliding window.
SimulatePython - 8
Measure key skew and the effect of salting
Partition 1,000,000 events by seller, by order and by salted seller, when one seller owns 40% of them.
SimulatePython - 9
How many keys move when N changes? Modulo vs. ring vs. rendezvous
Add an eleventh node: how many of 100,000 keys move under modulo hashing, a ring with 1 or 128 virtual nodes, and rendezvous hashing.
SimulatePython - 10
Break per-key order in a real Kafka topic, then repair it
Per-key order in Kafka, broken three ways (a worker pool, lost acks without idempotence, growing the topic) and repaired twice.
Real system · Break itDocker, Python - 11
A DLQ that does not become an outage amplifier
Write a small consumer with a retry-then-DLQ policy.
SimulatePython - 12
Choose N by measurement
Measure one consumer, derive the partition count, then compare N and 2N partitions for recovery time and files per hour.
Real system · MeasureDocker, Python - 13
What a rebalance repeats
Redeploy one consumer of a 12-member group on a 24-partition topic, many times: count what eager, cooperative and static membership process twice.
SimulatePython - 14
The length-prefix attack and the maximum frame size
A server that trusts a 4-byte length header, a header claiming 4 GB, and one wrong length in the middle of a stream.
Break itPython - 15
Batch size is a compression parameter
Compress 100,000 small JSON events in batches of 1 to 10,000, then with a trained dictionary.
MeasurePython with zstandard - 16
Compress or not: the rate comparison
compress + transfer + decompress against sending raw, for five codecs and three link speeds.
MeasurePython with lz4, zstandard - 17
Stale pooled connections: find out what your pool does
Exhaust a pool of 2, kill a proxy silently under a pooled connection, and read your HTTP library's defaults.
Break itPython with urllib3 - 18
Nagle plus delayed ACK: reproduce the 40 ms cliff
Two small writes and a short reply: Nagle on the sender and delayed ACK on the receiver add about 40 ms per call.
MeasurePython (Linux shows the effect) - 19
Dedup window versus replay
A 60-second dedup window against a replay five minutes later, then idempotency by replacing the partition.
SimulatePython - 20
Reconciliation count and duplicate-rate metric
Count records per hour at source and sink, then plant a bug that swallows 1% of writes: errors stay at zero, the count gap does not.
SimulatePython