skip to content

How do you size k and n in an erasure-coded object store to balance durability, storage cost and repair load?

level: principalimportance: should knowfreq 33%

answer

  1. two levers, different costs
  2. overhead is n over k
  3. repair amplification is k
  4. parity is capped by independent domains
  5. rebuild speed sets the exposure window

basics

~20 s

Set n minus k from the correlated failures placement can actually isolate, then pick k as wide as the repair and read fan-out can absorb, since overhead falls as k rises but repair reads k fragments. Rebuild speed matters as much as the parity count.

solid answer

~40 s

Two levers move independently. `n - k` sets how many simultaneous absences survive, and it is only meaningful up to the number of genuinely independent failure domains available: if one correlated unit can hold more than `n - k` fragments, the extra parity is decorative. `k` sets the economics — overhead is `n/k`, so widening `k` cuts storage, but every repair reads `k` fragments and every read fans out to `k` domains, so amplification and tail latency grow with it. The third input is repair time, because tolerating four absences only helps if the fifth does not arrive first; halving rebuild time often buys more durability than adding a parity fragment. Then decide what never enters the coded tier at all: small objects, hot objects and frequently mutated ones stay replicated.

go deeper

for a junior

The two numbers are not arbitrary: n minus k is how many pieces may be lost, and the ratio of n to k is how much storage the protection costs.

for a middle

Explain the tension. Widening k lowers overhead toward one but makes every repair read k fragments and every ordinary read contact k domains.

for a senior

Bring the operational inputs: independent domain count, the largest correlated failure unit, repair bandwidth under a domain loss, and the object-size threshold below which coding costs more than copying.

for a principal

Own the whole trade — where the tier boundary sits, whether the next unit of spend goes to parity or to rebuild throughput, and which correlated failures the code cannot help with at any width.

## The levers and what each one moves | Lever | Raises | Lowers | Real constraint | |---|---|---|---| | `n - k` (parity count) | losses tolerated | usable capacity | meaningless beyond the count of independent domains | | `k` (code width) | fan-out on reads and repair | storage overhead `n/k` | repair amplification equals `k` | | Rebuild throughput | effective durability | exposure window | competes with live read traffic | | Tier boundary | efficiency of the coded tier | fraction of the corpus coded | small, hot and mutable objects belong outside it | Storage overhead is `n/k`. Ten-of-fourteen is 1.4, twenty-of-twenty-four is 1.2 — the same four parity fragments amortised over twice the data. That is the pull toward wide codes, and it is entirely real. The push back is that repair reads `k` fragments and every ordinary read contacts `k` domains, so the wide code doubles repair amplification and doubles the number of responses whose slowest member sets the read's latency. ## The constraint placement imposes The code's arithmetic assumes independent losses. Placement is what delivers that assumption, and it sets a hard rule: **no correlated failure unit may hold more than `n - k` fragments of the same blob**. Correlated units are not only racks — a power feed, a firmware version, a switch, a deployment that rolls forward together, a single operator action. Two consequences follow. First, `n` cannot exceed the number of placement targets that fail independently, or fragments double up and the guarantee quietly weakens. Second, adding parity without adding independent domains buys almost nothing: the fifth parity fragment defends against a fifth independent loss in an environment whose failures arrive four-at-a-time by correlation. ## Repair time is half the durability answer Tolerating four absences only matters if the fifth does not arrive before the first four are repaired. Durability is therefore a function of the *window* between a loss and its repair as much as of `n - k`, and that window is set by rebuild throughput — which is itself throttled so repair does not crowd out live reads. This changes what to buy. Halving repair time shrinks the exposure window by half across every blob in the fleet, permanently, while one more parity fragment costs storage on every object forever and defends against an event whose probability may be dominated by correlation anyway. On a fleet where rebuilds are slow, repair investment usually beats parity investment. ## The tiering judgement Not everything should be coded, and deciding what stays replicated is part of sizing the code: - **Small objects.** Splitting a tiny object into `k` fragments produces pieces below the per-fragment metadata and minimum I/O size. The effective overhead exceeds replication's, and the object costs more coded than copied. A wider `k` pushes this threshold higher, which couples the width choice to the object-size distribution. - **Hot objects.** A read from one replica beats a `k`-way fan-out on latency and on request cost. Coding the hot set converts a storage saving into a tail-latency regression. - **Frequently mutated objects.** Every parity fragment depends on all `k` data fragments, so a partial update rewrites all the parity. Coded representations suit write-once data. The usual shape is replicate on write, then re-encode once an object is cold, large enough and stable. ## A decision order that works 1. Count the genuinely independent failure domains, and the largest correlated unit among them. That caps `n` and floors what `n - k` must be. 2. Set `n - k` from the failure events observed, not from a round number — including the concurrent-maintenance case, where planned work removes domains deliberately. 3. Measure the object-size distribution and set the coded-tier threshold where fragments stay above the per-fragment floor. 4. Choose `k` as the widest value whose repair amplification and read fan-out the fleet can carry under a realistic domain-loss scenario, not under steady state. 5. Model durability with rebuild time included, and compare the marginal parity fragment against the marginal repair bandwidth before spending on either. ## What to watch - Do not choose `k` and `n` from the storage ratio alone. That number is visible on a bill; the repair and fan-out costs are visible in an incident. - Do not add parity beyond the independent domains that exist to place it in. - Do not quote durability without a repair-time assumption, and say what throttle that assumes. - Do not code the whole corpus. The tier boundary is part of the design, not an exception to it.

  • Which objects would you leave on replication after moving bulk data to a coded tier?
    Small objects, where k fragments each fall below the per-fragment metadata and minimum I/O size, and hot objects, where a k-way read fan-out costs more tail latency than the storage saves. Frequently mutated objects too, since any partial update rewrites every parity fragment. Replicate on write, re-encode once cold.
  • How does repair speed enter the durability calculation?
    Tolerating four absences only helps if the fifth does not arrive first, so durability depends on the window between a loss and its repair. That window is set by rebuild throughput and the throttle protecting live reads, which is why halving repair time often buys more than adding a parity fragment.
  • Why not simply raise n minus k until durability is arbitrarily high?
    Each extra parity fragment costs storage on every object forever, needs another independent domain to be worth anything, and does nothing about the correlated failures that actually cause loss. Past a point the same money buys more from faster repair, better placement and end-to-end verification of what was reconstructed.

saying these in an interview costs you the question

  • Picks k and n from the storage ratio alone, ignoring repair and read fan-out.
  • Adds parity fragments without adding independent failure domains.
  • Quotes a durability figure with no rebuild-time assumption behind it.
  • Assumes a wider code is free because overhead falls as k rises.
  • Codes the entire corpus including small and frequently read objects.