Measure leverage and the cost of a cold restart
Simulate a modelNeeds Python with NumPy
Problem
A cache in front of a database answers a share h of the reads (the hit rate), so the database sees only the misses, a share 1 − h. The database is then sized for that remainder. That makes the cache's hit rate a lever on the layer below: the database's load is multiplied by 1/(1 − h) if the cache stops answering. At h = 0.95 the database is sized for one twentieth of the traffic, so a restart that empties the cache sends it twenty times its normal load until the cache refills.
See that hit rate is leverage, and that a restart is a load spike on the layer below.
- Run Postgres (or SQLite) with a table of 100,000 rows. Write a Python loop that reads keys drawn from a Zipf distribution (
numpy.random.zipf(1.2)modulo 100,000) and counts database reads. - Put a dictionary cache with LRU eviction (
collections.OrderedDict) in front. Use capacity 5,000 entries. Record hit rate h and database reads per 10,000 requests. - Compute leverage 1/(1 − h). Then clear the cache in the middle of the run and print database reads per second for the next 60 seconds.
The script uses SQLite and a steady 2,000 requests per second, counted in 100 ms ticks, so you can see the spike and how fast the cache refills.
The question. What hit rate does this cache reach, and how big is the database's load spike right after the cache is cleared, compared with 1/(1 − h)?
Predict
With h near 0.95 the database sees about 5% of the traffic. After the clear, the database sees close to 100% of the traffic for a short time, which is about 20 times more than its normal load. Write down the ratio you measure. It should be close to 1/(1 − h).
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
measure-leverage-and-the-cost-of.py # /// script # requires-python = ">=3.10" # dependencies = ["numpy"] # /// # Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT # https://thedataengineering.com/lab-code/LICENSE.txt """Measure leverage and the cost of a cold restart. A Zipf-distributed read stream against SQLite, first bare, then behind an LRU dictionary cache; then the cache is cleared mid-run and the database load is followed second by second at a steady request rate. """ import argparse, json, os, sqlite3, tempfile from collections import OrderedDict import numpy as np p = argparse.ArgumentParser(description=__doc__.splitlines()[0]) p.add_argument("--rows", type=int, default=100_000, help="Rows in the table (and distinct keys).") p.add_argument("--zipf", type=float, default=1.2, help="Zipf exponent of the key stream (numpy.random.zipf, modulo rows).") p.add_argument("--capacity", type=int, default=5_000, help="Cache capacity, in entries (LRU).") p.add_argument("--rate", type=int, default=2_000, help="Requests per second offered to the cache (the clock is the request count).") p.add_argument("--warm-seconds", type=int, default=30, help="Seconds of traffic before the cache is cleared.") p.add_argument("--after-seconds", type=int, default=60, help="Seconds of traffic followed after the clear.") p.add_argument("--seed", type=int, default=0, 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) # 1. The database: SQLite in a temporary file, one row per key path = os.path.join(tempfile.gettempdir(), "leverage-lab.db") import atexit; atexit.register(lambda: os.path.exists(path) and os.remove(path)) # leave nothing behind if os.path.exists(path): os.remove(path) db = sqlite3.connect(path) db.execute("CREATE TABLE kv (k INTEGER PRIMARY KEY, v TEXT)") db.executemany("INSERT INTO kv VALUES (?, ?)", ((k, f"value-{k}") for k in range(args.rows))) db.commit() db_reads = 0 def read_db(k): global db_reads db_reads += 1 return db.execute("SELECT v FROM kv WHERE k = ?", (k,)).fetchone()[0] def keys(n): return (rng.zipf(args.zipf, n) % args.rows).tolist() # 2. An LRU dictionary cache in front cache = OrderedDict() def get(k): if k in cache: cache.move_to_end(k); return cache[k] v = read_db(k) cache[k] = v if len(cache) > args.capacity: cache.popitem(last=False) return v # 3. Steady traffic in 100 ms ticks: database reads per second, the cache cleared after warm-seconds TICK = 10 # ticks per second per_tick = args.rate // TICK timeline = [] for tick in range((args.warm_seconds + args.after_seconds) * TICK): if tick == args.warm_seconds * TICK: cache.clear() before = db_reads for k in keys(per_tick): get(k) timeline.append({"second": (tick - args.warm_seconds * TICK) / TICK, "db_reads_per_s": (db_reads - before) * TICK}) warm = [t["db_reads_per_s"] for t in timeline if -10 <= t["second"] < 0] # the last 10 s before the clear steady_reads = sum(warm) / len(warm) h = 1 - steady_reads / args.rate leverage = 1 / (1 - h) peak = max(t["db_reads_per_s"] for t in timeline if t["second"] >= 0) recovered = next(t["second"] for t in timeline if t["second"] >= 0 and t["db_reads_per_s"] <= 1.5 * steady_reads) print(f"hit rate h = {h:.3f} -> leverage 1/(1-h) = {leverage:.1f}") print(f"database reads per 10,000 requests, warm: {steady_reads / args.rate * 10_000:,.0f} (without the cache: 10,000)") print(f"after the clear: peak {peak:,.0f} reads/s against {steady_reads:,.0f} reads/s warm = {peak / steady_reads:.1f}x " f"(1/(1-h) = {leverage:.1f}); back under 1.5x warm after {recovered:.1f} s") for t in [t for t in timeline if 0 <= t["second"] < 1]: print(f" {t['second']:.1f} s after clear: {t['db_reads_per_s']:>6,.0f} reads/s") if args.json: with open(args.json, "w") as f: json.dump({"tables": {"timeline": timeline, "summary": [{ "h": h, "leverage": leverage, "steady_reads": steady_reads, "peak_reads": peak, "spike": peak / steady_reads, "rate": args.rate, "recovered_s": recovered}]}}, 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 measure-leverage-and-the-cost-of.py uv run measure-leverage-and-the-cost-of.py --help # every knob
| Knob · default | What it changes |
|---|---|
| --rows100,000 | Rows in the table (and distinct keys). |
| --zipf1.2 | Zipf exponent of the key stream (numpy.random.zipf, modulo rows). |
| --capacity5000 | Cache capacity, in entries (LRU). |
| --rate2000 | Requests per second offered to the cache (the clock is the request count). |
| --warm-seconds30 | Seconds of traffic before the cache is cleared. |
| --after-seconds60 | Seconds of traffic followed after the clear. |
| --seed0 | Random seed. |
Our run
Data table
| Seconds from the clear | Database reads / s |
|---|---|
| -30 | 1,320 |
| -29.9 | 910 |
| -29.8 | 900 |
| -29.7 | 550 |
| -29.6 | 610 |
| -29.5 | 670 |
| -29.4 | 540 |
| -29.3 | 710 |
| -29.2 | 720 |
| -29.1 | 610 |
| -29 | 540 |
| -28.9 | 530 |
| -28.8 | 590 |
| -28.7 | 530 |
| -28.6 | 650 |
| -28.5 | 540 |
| -28.4 | 660 |
| -28.3 | 570 |
| -28.2 | 650 |
| -28.1 | 630 |
| -28 | 490 |
| -27.9 | 590 |
| -27.8 | 660 |
| -27.7 | 420 |
| -27.6 | 500 |
| -27.5 | 520 |
| -27.4 | 620 |
| -27.3 | 500 |
| -27.2 | 520 |
| -27.1 | 500 |
| -27 | 480 |
| -26.9 | 580 |
| -26.8 | 480 |
| -26.7 | 630 |
| -26.6 | 490 |
| -26.5 | 490 |
| -26.4 | 420 |
| -26.3 | 510 |
| -26.2 | 470 |
| -26.1 | 370 |
| -26 | 460 |
| -25.9 | 490 |
| -25.8 | 490 |
| -25.7 | 480 |
| -25.6 | 560 |
| -25.5 | 460 |
| -25.4 | 450 |
| -25.3 | 530 |
| -25.2 | 610 |
| -25.1 | 450 |
| -25 | 650 |
| -24.9 | 450 |
| -24.8 | 400 |
| -24.7 | 490 |
| -24.6 | 510 |
| -24.5 | 500 |
| -24.4 | 450 |
| -24.3 | 390 |
| -24.2 | 560 |
| -24.1 | 480 |
| -24 | 420 |
| -23.9 | 440 |
| -23.8 | 470 |
| -23.7 | 360 |
| -23.6 | 450 |
| -23.5 | 480 |
| -23.4 | 390 |
| -23.3 | 470 |
| -23.2 | 440 |
| -23.1 | 420 |
| -23 | 350 |
| -22.9 | 400 |
| -22.8 | 390 |
| -22.7 | 440 |
| -22.6 | 510 |
| -22.5 | 420 |
| -22.4 | 530 |
| -22.3 | 410 |
| -22.2 | 460 |
| -22.1 | 350 |
| -22 | 400 |
| -21.9 | 310 |
| -21.8 | 470 |
| -21.7 | 380 |
| -21.6 | 580 |
| -21.5 | 360 |
| -21.4 | 420 |
| -21.3 | 480 |
| -21.2 | 440 |
| -21.1 | 450 |
| -21 | 440 |
| -20.9 | 400 |
| -20.8 | 380 |
| -20.7 | 490 |
| -20.6 | 510 |
| -20.5 | 470 |
| -20.4 | 430 |
| -20.3 | 390 |
| -20.2 | 390 |
| -20.1 | 360 |
| -20 | 360 |
| -19.9 | 390 |
| -19.8 | 350 |
| -19.7 | 350 |
| -19.6 | 440 |
| -19.5 | 310 |
| -19.4 | 400 |
| -19.3 | 450 |
| -19.2 | 320 |
| -19.1 | 380 |
| -19 | 500 |
| -18.9 | 370 |
| -18.8 | 450 |
| -18.7 | 320 |
| -18.6 | 320 |
| -18.5 | 420 |
| -18.4 | 310 |
| -18.3 | 470 |
| -18.2 | 470 |
| -18.1 | 380 |
| -18 | 430 |
| -17.9 | 390 |
| -17.8 | 360 |
| -17.7 | 350 |
| -17.6 | 360 |
| -17.5 | 390 |
| -17.4 | 430 |
| -17.3 | 380 |
| -17.2 | 540 |
| -17.1 | 420 |
| -17 | 360 |
| -16.9 | 460 |
| -16.8 | 430 |
| -16.7 | 450 |
| -16.6 | 380 |
| -16.5 | 450 |
| -16.4 | 500 |
| -16.3 | 450 |
| -16.2 | 330 |
| -16.1 | 400 |
| -16 | 320 |
| -15.9 | 360 |
| -15.8 | 390 |
| -15.7 | 390 |
| -15.6 | 450 |
| -15.5 | 430 |
| -15.4 | 360 |
| -15.3 | 340 |
| -15.2 | 350 |
| -15.1 | 470 |
| -15 | 510 |
| -14.9 | 370 |
| -14.8 | 350 |
| -14.7 | 480 |
| -14.6 | 440 |
| -14.5 | 430 |
| -14.4 | 320 |
| -14.3 | 470 |
| -14.2 | 310 |
| -14.1 | 490 |
| -14 | 360 |
| -13.9 | 390 |
| -13.8 | 410 |
| -13.7 | 370 |
| -13.6 | 410 |
| -13.5 | 420 |
| -13.4 | 400 |
| -13.3 | 330 |
| -13.2 | 450 |
| -13.1 | 460 |
| -13 | 410 |
| -12.9 | 370 |
| -12.8 | 320 |
| -12.7 | 440 |
| -12.6 | 390 |
| -12.5 | 520 |
| -12.4 | 490 |
| -12.3 | 350 |
| -12.2 | 420 |
| -12.1 | 370 |
| -12 | 360 |
| -11.9 | 420 |
| -11.8 | 370 |
| -11.7 | 440 |
| -11.6 | 470 |
| -11.5 | 430 |
| -11.4 | 360 |
| -11.3 | 440 |
| -11.2 | 450 |
| -11.1 | 410 |
| -11 | 400 |
| -10.9 | 470 |
| -10.8 | 400 |
| -10.7 | 390 |
| -10.6 | 430 |
| -10.5 | 400 |
| -10.4 | 460 |
| -10.3 | 410 |
| -10.2 | 410 |
| -10.1 | 410 |
| -10 | 380 |
| -9.9 | 400 |
| -9.8 | 320 |
| -9.7 | 370 |
| -9.6 | 400 |
| -9.5 | 460 |
| -9.4 | 350 |
| -9.3 | 360 |
| -9.2 | 350 |
| -9.1 | 450 |
| -9 | 450 |
| -8.9 | 430 |
| -8.8 | 360 |
| -8.7 | 350 |
| -8.6 | 350 |
| -8.5 | 380 |
| -8.4 | 370 |
| -8.3 | 400 |
| -8.2 | 320 |
| -8.1 | 340 |
| -8 | 380 |
| -7.9 | 450 |
| -7.8 | 320 |
| -7.7 | 410 |
| -7.6 | 450 |
| -7.5 | 520 |
| -7.4 | 460 |
| -7.3 | 420 |
| -7.2 | 350 |
| -7.1 | 410 |
| -7 | 330 |
| -6.9 | 460 |
| -6.8 | 380 |
| -6.7 | 370 |
| -6.6 | 420 |
| -6.5 | 370 |
| -6.4 | 490 |
| -6.3 | 450 |
| -6.2 | 410 |
| -6.1 | 400 |
| -6 | 450 |
| -5.9 | 400 |
| -5.8 | 290 |
| -5.7 | 420 |
| -5.6 | 440 |
| -5.5 | 340 |
| -5.4 | 400 |
| -5.3 | 400 |
| -5.2 | 470 |
| -5.1 | 410 |
| -5 | 410 |
| -4.9 | 410 |
| -4.8 | 400 |
| -4.7 | 450 |
| -4.6 | 340 |
| -4.5 | 410 |
| -4.4 | 330 |
| -4.3 | 440 |
| -4.2 | 320 |
| -4.1 | 350 |
| -4 | 380 |
| -3.9 | 430 |
| -3.8 | 440 |
| -3.7 | 500 |
| -3.6 | 450 |
| -3.5 | 370 |
| -3.4 | 380 |
| -3.3 | 330 |
| -3.2 | 420 |
| -3.1 | 330 |
| -3 | 410 |
| -2.9 | 390 |
| -2.8 | 400 |
| -2.7 | 360 |
| -2.6 | 350 |
| -2.5 | 420 |
| -2.4 | 470 |
| -2.3 | 320 |
| -2.2 | 370 |
| -2.1 | 500 |
| -2 | 380 |
| -1.9 | 360 |
| -1.8 | 430 |
| -1.7 | 360 |
| -1.6 | 280 |
| -1.5 | 420 |
| -1.4 | 410 |
| -1.3 | 360 |
| -1.2 | 400 |
| -1.1 | 320 |
| -1 | 520 |
| -0.9 | 310 |
| -0.8 | 330 |
| -0.7 | 360 |
| -0.6 | 350 |
| -0.5 | 410 |
| -0.4 | 370 |
| -0.3 | 460 |
| -0.2 | 440 |
| -0.1 | 300 |
| 0 | 1,140 |
| 0.1 | 860 |
| 0.2 | 820 |
| 0.3 | 690 |
| 0.4 | 650 |
| 0.5 | 830 |
| 0.6 | 470 |
| 0.7 | 740 |
| 0.8 | 610 |
| 0.9 | 670 |
| 1 | 630 |
| 1.1 | 630 |
| 1.2 | 690 |
| 1.3 | 570 |
| 1.4 | 600 |
| 1.5 | 560 |
| 1.6 | 660 |
| 1.7 | 620 |
| 1.8 | 430 |
| 1.9 | 580 |
| 2 | 470 |
| 2.1 | 530 |
| 2.2 | 520 |
| 2.3 | 540 |
| 2.4 | 580 |
| 2.5 | 610 |
| 2.6 | 520 |
| 2.7 | 560 |
| 2.8 | 590 |
| 2.9 | 480 |
| 3 | 480 |
| 3.1 | 430 |
| 3.2 | 470 |
| 3.3 | 510 |
| 3.4 | 450 |
| 3.5 | 560 |
| 3.6 | 460 |
| 3.7 | 440 |
| 3.8 | 470 |
| 3.9 | 440 |
| 4 | 410 |
| 4.1 | 520 |
| 4.2 | 440 |
| 4.3 | 510 |
| 4.4 | 550 |
| 4.5 | 510 |
| 4.6 | 400 |
| 4.7 | 550 |
| 4.8 | 440 |
| 4.9 | 360 |
| 5 | 390 |
| 5.1 | 410 |
| 5.2 | 470 |
| 5.3 | 450 |
| 5.4 | 490 |
| 5.5 | 360 |
| 5.6 | 380 |
| 5.7 | 420 |
| 5.8 | 470 |
| 5.9 | 410 |
| 6 | 510 |
| 6.1 | 470 |
| 6.2 | 480 |
| 6.3 | 390 |
| 6.4 | 460 |
| 6.5 | 460 |
| 6.6 | 510 |
| 6.7 | 390 |
| 6.8 | 500 |
| 6.9 | 480 |
| 7 | 520 |
| 7.1 | 380 |
| 7.2 | 440 |
| 7.3 | 390 |
| 7.4 | 540 |
| 7.5 | 320 |
| 7.6 | 410 |
| 7.7 | 330 |
| 7.8 | 510 |
| 7.9 | 500 |
| 8 | 440 |
| 8.1 | 410 |
| 8.2 | 410 |
| 8.3 | 350 |
| 8.4 | 530 |
| 8.5 | 490 |
| 8.6 | 440 |
| 8.7 | 420 |
| 8.8 | 430 |
| 8.9 | 450 |
| 9 | 400 |
| 9.1 | 470 |
| 9.2 | 480 |
| 9.3 | 390 |
| 9.4 | 520 |
| 9.5 | 450 |
| 9.6 | 440 |
| 9.7 | 370 |
| 9.8 | 510 |
| 9.9 | 420 |
| 10 | 430 |
| 10.1 | 400 |
| 10.2 | 400 |
| 10.3 | 400 |
| 10.4 | 470 |
| 10.5 | 440 |
| 10.6 | 390 |
| 10.7 | 380 |
| 10.8 | 400 |
| 10.9 | 370 |
| 11 | 330 |
| 11.1 | 390 |
| 11.2 | 330 |
| 11.3 | 380 |
| 11.4 | 350 |
| 11.5 | 510 |
| 11.6 | 420 |
| 11.7 | 510 |
| 11.8 | 380 |
| 11.9 | 460 |
| 12 | 410 |
| 12.1 | 420 |
| 12.2 | 470 |
| 12.3 | 420 |
| 12.4 | 430 |
| 12.5 | 440 |
| 12.6 | 440 |
| 12.7 | 390 |
| 12.8 | 490 |
| 12.9 | 540 |
| 13 | 360 |
| 13.1 | 350 |
| 13.2 | 520 |
| 13.3 | 350 |
| 13.4 | 480 |
| 13.5 | 520 |
| 13.6 | 460 |
| 13.7 | 430 |
| 13.8 | 320 |
| 13.9 | 450 |
| 14 | 390 |
| 14.1 | 540 |
| 14.2 | 340 |
| 14.3 | 530 |
| 14.4 | 400 |
| 14.5 | 410 |
| 14.6 | 420 |
| 14.7 | 390 |
| 14.8 | 480 |
| 14.9 | 420 |
| 15 | 420 |
| 15.1 | 450 |
| 15.2 | 510 |
| 15.3 | 360 |
| 15.4 | 440 |
| 15.5 | 470 |
| 15.6 | 430 |
| 15.7 | 420 |
| 15.8 | 380 |
| 15.9 | 370 |
| 16 | 350 |
| 16.1 | 420 |
| 16.2 | 330 |
| 16.3 | 460 |
| 16.4 | 380 |
| 16.5 | 320 |
| 16.6 | 450 |
| 16.7 | 350 |
| 16.8 | 400 |
| 16.9 | 340 |
| 17 | 370 |
| 17.1 | 320 |
| 17.2 | 460 |
| 17.3 | 390 |
| 17.4 | 320 |
| 17.5 | 390 |
| 17.6 | 280 |
| 17.7 | 500 |
| 17.8 | 480 |
| 17.9 | 400 |
| 18 | 420 |
| 18.1 | 440 |
| 18.2 | 430 |
| 18.3 | 490 |
| 18.4 | 350 |
| 18.5 | 440 |
| 18.6 | 310 |
| 18.7 | 440 |
| 18.8 | 300 |
| 18.9 | 370 |
| 19 | 400 |
| 19.1 | 360 |
| 19.2 | 330 |
| 19.3 | 400 |
| 19.4 | 380 |
| 19.5 | 350 |
| 19.6 | 430 |
| 19.7 | 410 |
| 19.8 | 500 |
| 19.9 | 380 |
| 20 | 510 |
| 20.1 | 410 |
| 20.2 | 410 |
| 20.3 | 340 |
| 20.4 | 280 |
| 20.5 | 340 |
| 20.6 | 330 |
| 20.7 | 470 |
| 20.8 | 380 |
| 20.9 | 430 |
| 21 | 350 |
| 21.1 | 470 |
| 21.2 | 400 |
| 21.3 | 430 |
| 21.4 | 340 |
| 21.5 | 440 |
| 21.6 | 440 |
| 21.7 | 420 |
| 21.8 | 410 |
| 21.9 | 430 |
| 22 | 410 |
| 22.1 | 400 |
| 22.2 | 360 |
| 22.3 | 390 |
| 22.4 | 420 |
| 22.5 | 430 |
| 22.6 | 400 |
| 22.7 | 370 |
| 22.8 | 420 |
| 22.9 | 370 |
| 23 | 400 |
| 23.1 | 370 |
| 23.2 | 410 |
| 23.3 | 480 |
| 23.4 | 370 |
| 23.5 | 330 |
| 23.6 | 470 |
| 23.7 | 410 |
| 23.8 | 370 |
| 23.9 | 400 |
| 24 | 340 |
| 24.1 | 470 |
| 24.2 | 370 |
| 24.3 | 370 |
| 24.4 | 380 |
| 24.5 | 440 |
| 24.6 | 430 |
| 24.7 | 490 |
| 24.8 | 420 |
| 24.9 | 270 |
| 25 | 320 |
| 25.1 | 400 |
| 25.2 | 430 |
| 25.3 | 490 |
| 25.4 | 470 |
| 25.5 | 460 |
| 25.6 | 440 |
| 25.7 | 460 |
| 25.8 | 310 |
| 25.9 | 430 |
| 26 | 500 |
| 26.1 | 360 |
| 26.2 | 260 |
| 26.3 | 340 |
| 26.4 | 420 |
| 26.5 | 470 |
| 26.6 | 480 |
| 26.7 | 470 |
| 26.8 | 500 |
| 26.9 | 490 |
| 27 | 320 |
| 27.1 | 350 |
| 27.2 | 370 |
| 27.3 | 360 |
| 27.4 | 380 |
| 27.5 | 470 |
| 27.6 | 330 |
| 27.7 | 380 |
| 27.8 | 500 |
| 27.9 | 410 |
| 28 | 360 |
| 28.1 | 510 |
| 28.2 | 500 |
| 28.3 | 410 |
| 28.4 | 380 |
| 28.5 | 450 |
| 28.6 | 440 |
| 28.7 | 390 |
| 28.8 | 430 |
| 28.9 | 430 |
| 29 | 360 |
| 29.1 | 490 |
| 29.2 | 510 |
| 29.3 | 380 |
| 29.4 | 440 |
| 29.5 | 380 |
| 29.6 | 440 |
| 29.7 | 400 |
| 29.8 | 440 |
| 29.9 | 380 |
| 30 | 400 |
| 30.1 | 500 |
| 30.2 | 500 |
| 30.3 | 490 |
| 30.4 | 330 |
| 30.5 | 360 |
| 30.6 | 370 |
| 30.7 | 550 |
| 30.8 | 420 |
| 30.9 | 560 |
| 31 | 380 |
| 31.1 | 390 |
| 31.2 | 500 |
| 31.3 | 400 |
| 31.4 | 440 |
| 31.5 | 400 |
| 31.6 | 440 |
| 31.7 | 420 |
| 31.8 | 400 |
| 31.9 | 380 |
| 32 | 550 |
| 32.1 | 480 |
| 32.2 | 380 |
| 32.3 | 380 |
| 32.4 | 420 |
| 32.5 | 520 |
| 32.6 | 430 |
| 32.7 | 420 |
| 32.8 | 290 |
| 32.9 | 380 |
| 33 | 510 |
| 33.1 | 340 |
| 33.2 | 510 |
| 33.3 | 390 |
| 33.4 | 530 |
| 33.5 | 320 |
| 33.6 | 410 |
| 33.7 | 440 |
| 33.8 | 320 |
| 33.9 | 360 |
| 34 | 380 |
| 34.1 | 490 |
| 34.2 | 420 |
| 34.3 | 390 |
| 34.4 | 400 |
| 34.5 | 370 |
| 34.6 | 520 |
| 34.7 | 360 |
| 34.8 | 470 |
| 34.9 | 390 |
| 35 | 520 |
| 35.1 | 510 |
| 35.2 | 440 |
| 35.3 | 470 |
| 35.4 | 360 |
| 35.5 | 420 |
| 35.6 | 370 |
| 35.7 | 440 |
| 35.8 | 390 |
| 35.9 | 430 |
| 36 | 300 |
| 36.1 | 410 |
| 36.2 | 370 |
| 36.3 | 410 |
| 36.4 | 470 |
| 36.5 | 400 |
| 36.6 | 390 |
| 36.7 | 430 |
| 36.8 | 390 |
| 36.9 | 440 |
| 37 | 500 |
| 37.1 | 380 |
| 37.2 | 480 |
| 37.3 | 440 |
| 37.4 | 430 |
| 37.5 | 470 |
| 37.6 | 460 |
| 37.7 | 330 |
| 37.8 | 390 |
| 37.9 | 440 |
| 38 | 460 |
| 38.1 | 480 |
| 38.2 | 460 |
| 38.3 | 430 |
| 38.4 | 440 |
| 38.5 | 420 |
| 38.6 | 400 |
| 38.7 | 480 |
| 38.8 | 420 |
| 38.9 | 460 |
| 39 | 370 |
| 39.1 | 360 |
| 39.2 | 360 |
| 39.3 | 450 |
| 39.4 | 350 |
| 39.5 | 460 |
| 39.6 | 460 |
| 39.7 | 340 |
| 39.8 | 460 |
| 39.9 | 380 |
| 40 | 320 |
| 40.1 | 490 |
| 40.2 | 450 |
| 40.3 | 450 |
| 40.4 | 530 |
| 40.5 | 470 |
| 40.6 | 390 |
| 40.7 | 400 |
| 40.8 | 500 |
| 40.9 | 400 |
| 41 | 370 |
| 41.1 | 320 |
| 41.2 | 410 |
| 41.3 | 500 |
| 41.4 | 330 |
| 41.5 | 350 |
| 41.6 | 400 |
| 41.7 | 340 |
| 41.8 | 450 |
| 41.9 | 450 |
| 42 | 410 |
| 42.1 | 450 |
| 42.2 | 560 |
| 42.3 | 350 |
| 42.4 | 350 |
| 42.5 | 410 |
| 42.6 | 430 |
| 42.7 | 480 |
| 42.8 | 370 |
| 42.9 | 330 |
| 43 | 310 |
| 43.1 | 450 |
| 43.2 | 390 |
| 43.3 | 450 |
| 43.4 | 570 |
| 43.5 | 410 |
| 43.6 | 360 |
| 43.7 | 410 |
| 43.8 | 380 |
| 43.9 | 460 |
| 44 | 520 |
| 44.1 | 400 |
| 44.2 | 340 |
| 44.3 | 350 |
| 44.4 | 450 |
| 44.5 | 380 |
| 44.6 | 470 |
| 44.7 | 320 |
| 44.8 | 420 |
| 44.9 | 420 |
| 45 | 360 |
| 45.1 | 370 |
| 45.2 | 460 |
| 45.3 | 380 |
| 45.4 | 380 |
| 45.5 | 310 |
| 45.6 | 390 |
| 45.7 | 410 |
| 45.8 | 350 |
| 45.9 | 460 |
| 46 | 390 |
| 46.1 | 380 |
| 46.2 | 360 |
| 46.3 | 390 |
| 46.4 | 400 |
| 46.5 | 430 |
| 46.6 | 360 |
| 46.7 | 470 |
| 46.8 | 450 |
| 46.9 | 390 |
| 47 | 280 |
| 47.1 | 500 |
| 47.2 | 390 |
| 47.3 | 450 |
| 47.4 | 540 |
| 47.5 | 400 |
| 47.6 | 380 |
| 47.7 | 430 |
| 47.8 | 390 |
| 47.9 | 490 |
| 48 | 370 |
| 48.1 | 310 |
| 48.2 | 490 |
| 48.3 | 420 |
| 48.4 | 470 |
| 48.5 | 350 |
| 48.6 | 370 |
| 48.7 | 450 |
| 48.8 | 460 |
| 48.9 | 280 |
| 49 | 320 |
| 49.1 | 410 |
| 49.2 | 430 |
| 49.3 | 380 |
| 49.4 | 370 |
| 49.5 | 420 |
| 49.6 | 320 |
| 49.7 | 350 |
| 49.8 | 470 |
| 49.9 | 330 |
| 50 | 440 |
| 50.1 | 420 |
| 50.2 | 430 |
| 50.3 | 440 |
| 50.4 | 440 |
| 50.5 | 450 |
| 50.6 | 450 |
| 50.7 | 410 |
| 50.8 | 350 |
| 50.9 | 380 |
| 51 | 380 |
| 51.1 | 430 |
| 51.2 | 610 |
| 51.3 | 450 |
| 51.4 | 400 |
| 51.5 | 460 |
| 51.6 | 430 |
| 51.7 | 450 |
| 51.8 | 430 |
| 51.9 | 380 |
| 52 | 390 |
| 52.1 | 360 |
| 52.2 | 400 |
| 52.3 | 380 |
| 52.4 | 580 |
| 52.5 | 440 |
| 52.6 | 340 |
| 52.7 | 460 |
| 52.8 | 440 |
| 52.9 | 380 |
| 53 | 360 |
| 53.1 | 520 |
| 53.2 | 330 |
| 53.3 | 490 |
| 53.4 | 390 |
| 53.5 | 430 |
| 53.6 | 350 |
| 53.7 | 400 |
| 53.8 | 410 |
| 53.9 | 410 |
| 54 | 390 |
| 54.1 | 300 |
| 54.2 | 360 |
| 54.3 | 350 |
| 54.4 | 500 |
| 54.5 | 470 |
| 54.6 | 460 |
| 54.7 | 410 |
| 54.8 | 380 |
| 54.9 | 440 |
| 55 | 290 |
| 55.1 | 330 |
| 55.2 | 340 |
| 55.3 | 450 |
| 55.4 | 490 |
| 55.5 | 420 |
| 55.6 | 350 |
| 55.7 | 460 |
| 55.8 | 480 |
| 55.9 | 410 |
| 56 | 430 |
| 56.1 | 470 |
| 56.2 | 390 |
| 56.3 | 440 |
| 56.4 | 440 |
| 56.5 | 490 |
| 56.6 | 430 |
| 56.7 | 520 |
| 56.8 | 410 |
| 56.9 | 440 |
| 57 | 370 |
| 57.1 | 400 |
| 57.2 | 330 |
| 57.3 | 480 |
| 57.4 | 330 |
| 57.5 | 440 |
| 57.6 | 350 |
| 57.7 | 350 |
| 57.8 | 390 |
| 57.9 | 340 |
| 58 | 310 |
| 58.1 | 460 |
| 58.2 | 460 |
| 58.3 | 450 |
| 58.4 | 490 |
| 58.5 | 360 |
| 58.6 | 420 |
| 58.7 | 380 |
| 58.8 | 300 |
| 58.9 | 380 |
| 59 | 420 |
| 59.1 | 450 |
| 59.2 | 260 |
| 59.3 | 370 |
| 59.4 | 410 |
| 59.5 | 320 |
| 59.6 | 330 |
| 59.7 | 490 |
| 59.8 | 390 |
| 59.9 | 430 |
hit rate h = 0.803 -> leverage 1/(1-h) = 5.1
database reads per 10,000 requests, warm: 1,966 (without the cache: 10,000)
after the clear: peak 1,140 reads/s against 393 reads/s warm = 2.9x (1/(1-h) = 5.1); back under 1.5x warm after 0.6 s
0.0 s after clear: 1,140 reads/s
0.1 s after clear: 860 reads/s
0.2 s after clear: 820 reads/s
0.3 s after clear: 690 reads/s
0.4 s after clear: 650 reads/s
0.5 s after clear: 830 reads/s
0.6 s after clear: 470 reads/s
0.7 s after clear: 740 reads/s
0.8 s after clear: 610 reads/s
0.9 s after clear: 670 reads/sWhat we found
This cache reached h = 0.803, below the 0.95 the chapter assumes: with 5,000 slots for 100,000 Zipf-1.2 keys, about one request in five still misses. That puts the leverage at 5.09×: the database saw 393 reads per second out of 2,000 requests.
Right after the clear the database load jumped to 1,140 reads per second, 2.9× its warm load. That is below the 5.09× that 1/(1 − h) gives, and the spike was short: the load was back under 1.5× warm after 0.6 s. The reason is the Zipf skew. The hottest keys come back within the first few dozen requests, so even the first 100 ms already has hits. The spike reaches the full 1/(1 − h) only for the first handful of requests, or when the cache is so large relative to the request rate that refilling it takes minutes.
Read it
Leverage is the number to watch, not the hit rate. Going from h = 0.90 to h = 0.95 looks like a 5-point improvement; it halves the load on the database and doubles the multiple it faces when the cache is lost. A cache that succeeds becomes a dependency nobody drew on the design: the database is now sized for the misses, not for the traffic.
This is why warming exists. Its purpose is not lower latency but survivability: after a restart, traffic is ramped back at the rate the database can absorb, not all at once. How long the spike lasts depends on how fast the cache refills, which depends on how concentrated the traffic is and how big the cache is.