Anomaly count equals rate times window
Simulate a modelNeeds Python with NumPy
Problem
A consistency anomaly needs two operations close enough in time to conflict: a write and a read inside the replication lag, two transactions inside each other's read-then-write gap. By Little's rule, the number of operations inside a window W at any moment is the arrival rate times the window: λ × W. So the exposure to anomalies is set by two terms, and the window is the one you control. The same code is a hundred times more exposed when replica lag grows from 20 ms to 2 s, and a thousand times less exposed when a read-modify-write happens inside one statement instead of across two round trips.
Simulate conflicting operations arriving at random (a Poisson process) and count how many fall inside a window W of an earlier operation. Compare with λ × W for W = 20 ms (normal replica lag), 2 s (lag under load), 50 ms (application read-modify-write) and 50 µs (one SQL statement).
The script also sweeps a range of windows in between, for the chart.
The question. At 667 conflicting operations per second, how many fall inside each window, and how far apart are a 50 ms application read-modify-write and a 50 µs single statement?
Predict
Expect the measured average to match λ × W (about 13.3 for 20 ms, about 1,334 for 2 s, about 33 for 50 ms, about 0.033 for 50 µs). The last two differ by a factor of about 1,000.
Run it
1Install uv once. It fetches Python and the lab's packages for you.
Terminal curl -LsSf https://astral.sh/uv/install.sh | sh2Get the script. It is the whole lab: read it, then download it.
View the codeHide the code
anomaly-count-equals-rate-times-window.py # /// script # requires-python = ">=3.10" # dependencies = ["numpy"] # /// # Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT # https://thedataengineering.com/lab-code/LICENSE.txt """Anomaly count equals rate times window. Conflicting operations arrive at random (a Poisson process); for each one, count how many others fall inside a window W after it, and compare the average with lambda x W for windows from one SQL statement to lag under load. """ import argparse, json import numpy as np p = argparse.ArgumentParser(description=__doc__.splitlines()[0]) p.add_argument("--rate", type=float, default=667, help="lambda: conflicting operations per second (667/s = 40,000 per minute).") p.add_argument("--seconds", type=float, default=60, help="Simulated time.") p.add_argument("--seed", type=int, default=7, help="Random seed.") p.add_argument("--json", help="Also write the results to this JSON file.") args = p.parse_args() rng = np.random.default_rng(args.seed) lam, T = args.rate, args.seconds n = rng.poisson(lam * T) t = np.sort(rng.uniform(0, T, n)) named = [("single statement 50us", 50e-6), ("replica lag 20ms", 0.020), ("app read-modify-write 50ms", 0.050), ("lag under load 2s", 2.0)] grid = sorted(set([w for _, w in named] + list(np.logspace(-5, 0.5, 12)))) rows = [] for W in grid: inside = np.searchsorted(t, t + W) - np.arange(n) - 1 # other operations in the next W seconds rows.append({"window_s": float(W), "measured": float(inside.mean()), "lambda_W": lam * W}) for name, W in named: r = next(r for r in rows if r["window_s"] == W) print(f"{name:30s} measured {r['measured']:10.4f} lambda*W {r['lambda_W']:10.4f}") a, b = (next(r for r in rows if r["window_s"] == W)["measured"] for W in (0.050, 50e-6)) print(f"\napp read-modify-write window / single statement window: {a / b:,.0f}x more conflicts") if args.json: with open(args.json, "w") as f: json.dump({"tables": {"windows": rows, "named": [{"window": nm, **next(r for r in rows if r["window_s"] == W)} for nm, W in named], "summary": [{"ratio": a / b, "n": int(n)}]}}, f)3Run it in the folder you saved it to, with the defaults first. Then change a knob from the table below and run it again.
Terminal uv run anomaly-count-equals-rate-times-window.py uv run anomaly-count-equals-rate-times-window.py --help # every knob
| Knob · default | What it changes |
|---|---|
| --rate667 | lambda: conflicting operations per second (667/s = 40,000 per minute). |
| --seconds60 | Simulated time. |
| --seed7 | Random seed. |
Our run
Data table
| Window (seconds) | Measured | λ × W |
|---|---|---|
| 10 µs | 0.007 | 0.007 |
| 31.6 µs | 0.022 | 0.021 |
| 50 µs | 0.034 | 0.033 |
| 100 µs | 0.067 | 0.067 |
| 316 µs | 0.211 | 0.211 |
| 1 ms | 0.666 | 0.667 |
| 3.16 ms | 2.11 | 2.11 |
| 10 ms | 6.66 | 6.67 |
| 20 ms | 13.3 | 13.3 |
| 31.6 ms | 21.1 | 21.1 |
| 50 ms | 33.4 | 33.4 |
| 100 ms | 66.8 | 66.7 |
| 316 ms | 211 | 211 |
| 1 s | 663 | 667 |
| 2 s | 1,320 | 1,330 |
| 3.16 s | 2,060 | 2,110 |
The four windows
| Window | Measured | λ × W |
|---|---|---|
| single statement 50us | 0.034 | 0.033 |
| replica lag 20ms | 13.3 | 13.3 |
| app read-modify-write 50ms | 33.4 | 33.4 |
| lag under load 2s | 1,320 | 1,330 |
single statement 50us measured 0.0341 lambda*W 0.0334
replica lag 20ms measured 13.3480 lambda*W 13.3400
app read-modify-write 50ms measured 33.4035 lambda*W 33.3500
lag under load 2s measured 1315.1177 lambda*W 1334.0000
app read-modify-write window / single statement window: 978x more conflictsWhat we found
The measured averages matched λ × W across five orders of magnitude of window, as expected: 13.3 for 20 ms of replica lag, 1,320 for 2 s, 33.4 for a 50 ms application read-modify-write and 0.034 for a 50 µs statement. The application round trip exposed 978× more conflicting operations than the single statement.
Read it
This is the window argument of Transactional isolation.
Anomalies in flight ≈ conflicting rate × window. You rarely control the rate; you always control the window. Move a read-modify-write into one statement (SET balance = balance + 50), shorten replica lag, send a user's reads to the primary just after that user writes: each shrinks W, and the exposure shrinks with it, without changing the isolation level.