learn-data-reliability-with-phoebe / Builder session 2 of 8
Learn Data Reliability with Phoebe · Builder session 2 of 8

SLOs from history, not hope

Session 1 ended with one honest number: Harborlight's orders pipeline landed 685 of 720 partitions good last month, 95.14 percent. Tonight that number becomes a promise. The service-reliability literature is blunt about how: read the history, pick a target you can keep without heroics, and tighten it later when you have earned the right. Four candidates are on the table - 95, 97, 99 and 99.9 - and the same thirty nights tell you exactly which night each one would have broken. Only one survives to night 30.

🟡 Core Data and analytics engineers 45 min
0-3 · Welcome 3-20 · Reading the history before writing the target 20-40 · Build-along: set one target 40-45 · Q&A
Part 0

Where tonight sits in the builder track

Eight sessions, one artifact: a reliability contract for one pipeline. Session 1 produced the indicator and the number. Tonight produces the target - the line in the contract that says how much failure the reader has agreed to absorb - and the date on which it may move. Session 3 turns the gap between target and history into an error budget and pages on how fast it burns. Nothing tonight requires more than the partition log you already have and a window function.

Live = presented in the 45 minutes Self-study = the full depth, after class 🔍 Every diagram zooms

★ What you walk out with tonight. A target for one pipeline that the last thirty nights actually support, written with its window and its review date. The arithmetic that shows what each candidate target would have done to last month - 95 percent ends the month with 3 percent of budget left, 97 is exhausted on night 15, 99 on night 9, 99.9 on night 4. And a clear view of the trap most teams walk into: promising the typical night for every night.

LiveWhy the target is the second decision, never the first3 min▶

An SLO is a target value for an SLI. That definition has an order in it: the indicator exists first, and the target is a value on its scale. A team that sets "99 percent" before it has an indicator has set a target on nothing, and the first thing the indicator does when it arrives is embarrass the target.

Harborlight had lived with "basically 99" for a year. The number came from a meeting, not a query, and the settlement team had planned around it: a manual check on the report at 7 am, no contingency for a late one. When the measured month came in at 95.14, the target was not merely wrong; a downstream team had built a morning around it. That is what a target does. People plan on it. So it has to be a number the pipeline can keep.

Real world

The first draft of Harborlight's contract said 99 percent because "that is what the other pipelines promise". None of the other pipelines had been measured either. When all four were run through the same partition-log query, two were under 97 and one was at 91. The 99 had been copied from pipeline to pipeline for two years without a single measurement behind it.

Self-studyThe vocabulary tonight adds3 min▶
  • Target - the value of the SLI the reader has agreed is good enough, over a stated window. "95 percent of hourly partitions good over any rolling 30 days."
  • Achieved - what the SLI actually returned over the same window. Harborlight: 95.14 percent. The target is chosen against this, and below it.
  • Error budget - one hundred percent minus the target, in events. At 95 percent over 720 partitions that is 36 bad partitions; at 99.9 it is 0.72. Session 3 spends it hour by hour; tonight it only decides which night the budget runs out.
  • Exhaustion night - the first night the cumulative count of bad partitions exceeds the budget. From that night on, the promise is broken regardless of what happens next.
  • The p50 night - the median night's compliance. At Harborlight the median night is clean, 24 of 24. Promising that for every night is the 99.9 trap.
  • Review date - the date the target is allowed to change. A target without one either never moves or moves in every argument.
Part 1 · covers choosing the target

The history already knows the answer

9 min live

The service-reliability guidance on picking a target is short and every line of it is about restraint: don't pick based on current performance, keep it simple, avoid absolutes, have as few SLOs as possible, perfection can wait. The apparent contradiction - do not pick from current performance, yet read the history - resolves the moment you see what each is guarding against.

Cumulative bad partitions, thirty nights, against four budgets 0 20 40 night 1 4 9 15 21 27 30 95% · 36 97% · 21.6 99% · 7.2 99.9% · 0.72 night 4: 99.9 gone night 9: 17 bad, 99 gone night 15: 23 bad, 97 gone night 21: 31 night 27: 35, one under 36 The curve is the same for every target. Only the line it has to stay under moves.
🔍 Click to zoom - one month of bad partitions against four budgets, and the night each one is crossed.
LiveWhat the guidance actually says, line by line4 min▶
  • "Don't pick based on current performance." The warning is against locking in a heroic month. If the pipeline hit 99.6 last month because two engineers babysat it through a migration, 99.6 is not what the pipeline delivers; it is what the two engineers delivered, and they will not do it every month.
  • "Keep it simple." One target, one window, one indicator. A target with a weekday clause, a holiday exemption and a separate number for the last hour of the day is a target nobody can hold in their head, which means nobody can plan around it.
  • "Avoid absolutes." 100 percent is not a target; it is a wish. It leaves no budget at all, so the first bad partition of the month is a broken promise and every night after it is indistinguishable from the last.
  • "Have as few SLOs as possible." Each one is a promise somebody has to check, report and defend. Three that matter beat twelve that get ignored.
  • "Perfection can wait." The full phrasing is that it is better to start with a loose target that you tighten. A loose target kept teaches the reader to trust the number; a tight one broken teaches them to ignore it.
LiveThe contradiction that is not one3 min▶

"Do not pick from current performance" and "read the history before you write the target" sound opposed. They are two halves of one rule. The history tells you what the pipeline achieves without heroics: the typical month, the bad month, the spread between them. Current performance, in the sense the guidance warns against, is the best recent number. You read the history to find the typical month, and you set the target below it, not at the best one.

Harborlight's typical month is around 95 to 96 percent. Its best recent month was the migration month at 99.6. Its best recent night is 24 of 24, and 25 of the last 30 nights look like that. The target that the guidance points to is under 95.14: a number the pipeline clears in an ordinary month with nobody staying late. The numbers it warns against are 99.6 and 99.9.

Real world

The settlement team's first reaction to "95 percent" was that it sounded low. The reply that landed: at 95 percent, last month would have been a kept promise with one partition to spare. At 99, the promise would have been broken on night 9 and every settlement report from night 10 onward would have been produced under a contract already in default. They chose the promise that would have been kept.

Self-studyThe four candidates and what each does to the month4 min▶

Same thirty nights, same 35 bad partitions clustered in five incidents. The only thing that changes across the rows is the budget, which is one hundred percent minus the target, times 720.

TargetBudget (bad partitions allowed)Budget left at night 30Exhausted on night
95 percent363 percentnever
97 percent21.6015
99 percent7.209
99.9 percent, the p50 night promised every night0.7204
  • 95 percent survives the month by one partition. That is real headroom, but thin: one more bad hour on night 27 and it breaks on night 27 instead.
  • 97 percent survives the late load and the outage and dies on the corrupt batch. Night 15's six bad partitions take the count from 17 to 23 against a budget of 21.6.
  • 99 percent allows 7.2 bad partitions. The outage on night 9 alone is 14. The promise does not survive a single incident of that shape.
  • 99.9 percent allows 0.72 of a partition. Less than one. The three late partitions on night 4 are four times the whole month's budget.
Part 2 · covers the loose-then-tighten path

The 99.9 trap, and what a loose target buys

8 min live

99.9 percent is the most common wrong answer, and it is wrong for an interesting reason: on most nights it is true. Twenty-five of Harborlight's last thirty nights landed all 24 partitions. Anyone looking at a dashboard of nightly compliance sees a wall of clean nights and a number that starts with 99. The month is not made of the median night.

Nightly compliance, sorted best to worst 100 70 40 25 of 30 nights land all 24 partitions n4 n27 n15 n21 n9 87.5 83.3 75 66.7 41.7 month 95.14 target 95 p50 night: 24/24 promised for every night = 99.9 budget 0.72, gone on night 4 The month is the area under all thirty bars, not the height of the middle one.
🔍 Click to zoom - the median night is clean, the month is 95.14, and the honest target sits just under the month.
LiveWhy 99.9 looks reasonable in a meeting and fails as a monthly promise3 min▶

In the meeting, someone has the nightly dashboard open. Twenty-five green nights out of thirty. The median night is perfect. "We are basically at three nines" is a true statement about the typical night and a false statement about the month, and the room hears the second one.

As a monthly promise, 99.9 percent of 720 partitions allows 0.72 bad partitions. That is not one bad partition; it is less than one. The first incident of any size breaks it, and Harborlight's first incident was the smallest of the five: three late partitions on night 4, four times the month's entire budget. From night 4 to night 30 the pipeline is in breach, and the 26 clean nights that follow do nothing to change that, because a broken promise does not heal.

The tell. If the proposed target is higher than the achieved number for the month, somebody is reading the median night. Harborlight's month is 95.14. Anything above that is a promise the last thirty nights already broke.

LiveWhat a loose target buys the reader3 min▶

A 95 percent promise the pipeline keeps is worth more to the settlement team than a 99 percent promise it breaks on night 9. That sounds backwards until you ask what the reader does with the number. They plan around it. A kept 95 tells them: expect roughly one bad partition in twenty, build the morning check to tolerate it, and trust the report the rest of the time. A broken 99 tells them nothing, because from night 10 the contract is in default and every report after it carries the same asterisk.

  • Kept promises compound. Three months of a kept 95 and the reader stops re-checking the report by hand. Three months of a broken 99 and they build a shadow process.
  • Budget is a currency only while there is some. At 95, there is budget left on night 30 to decide whether a risky backfill can run tonight. At 99, that decision was taken away on night 9.
  • A loose target is not a low bar. It is the bar the history clears. 95 percent still means 36 bad partitions a month is the ceiling, and last month used 35 of them.
Self-studyTightening is earned at the quarterly review3 min▶

The target moves on a date, not in an argument. Harborlight's contract names the first day of the next quarter, and it names what has to be true by then for 95 to become 97: the coverage check from session 1 in production for the whole quarter, and the connector retry that the night 21 postmortem asked for, shipped and observed through at least one flapping night.

  • Tighten after the fix, not before it. A tighter target does not make the pipeline more reliable; the fix does. The target follows the evidence that the fix worked.
  • One step at a time. 95 to 97 is a budget of 36 falling to 21.6. Going to 99 in one move is a budget of 7.2, which last month's outage alone would have doubled.
  • Loosening is allowed too. If a quarter's history says the pipeline no longer clears the target without heroics, the honest move is down, with the reason written in the contract. A target that only ever tightens is a target that will eventually be ignored.
Self-studyRolling thirty days, not the calendar month2 min▶

The window in the contract is any rolling 30 days, and the query computes it for every night. A calendar month does something worse than being imprecise: it resets the budget at midnight on the first. Everybody learns that the safest time to ship a risky change is the second of the month, when the budget is full and the consequences of spending it are four weeks away. A rolling window has no such day. The budget you spend on the second is still gone on the twentieth.

If the platform you inherit reports SLO compliance by calendar month, the target line can stay, but the review conversation needs a one-line note: the calendar number and the rolling number will differ, and the rolling one is the honest one.

Build-along

Set one target from your own history

★ 20 min · everyone builds

Use the partition log and the combined good-event definition from session 1. Ninety days of history is comfortable; thirty is the minimum. The Harborlight answers are in the comments so you can check your arithmetic as you go.

Compute the achieved SLI per rolling 30-day window over the last 90 days. Aggregate to nights first, then a window function sums good and total over the current night and the 29 before it. You get 90 numbers; the spread between them is the honest picture of what the pipeline delivers.

Compute the distribution of nightly compliance and look at the p50 night. This is the trap made visible: the median night is clean while the month is 95.14. Also take the worst night. Night 9 landed 10 of 24, and any target that cannot absorb a night like that is a target the history has already broken.

Compute the budget in partitions at 95, 97, 99 and 99.9. One hundred percent minus the target, times the events in the window. Notice that 99.9 gives less than one partition.

For each target, find the night the cumulative bad count first exceeds the budget. A running sum over nights and a filter for the first crossing. The nights that come back - never, 15, 9, 4 - are the whole argument for the target you are about to write.

Write the target you would sign, and the quarterly date it may move. Below the typical month, above the worst month you would tolerate, with the window stated and the conditions for tightening named. Then read it to the person who signs the report.

★ Step 1 · rolling 30-day SLI, one row per night with events as ( select partition_hour, date_trunc('day', partition_hour) as night, landed_at <= partition_hour + interval '60 minute' and reconciled and row_count >= 0.9 * lag(row_count, 168) over (order by partition_hour) as good from ops.orders_partition_log where partition_hour >= dateadd('day', -127, current_timestamp) -- 90 nights + 30 for the first window + 7 for the lag ), nightly as ( select night, count(*) as total, count_if(good) as good from events group by night ) select night, sum(good) over (order by night rows between 29 preceding and current row) as good_30d, sum(total) over (order by night rows between 29 preceding and current row) as total_30d, good_30d / total_30d::float as rolling_sli from nightly where night >= dateadd('day', -90, current_date) order by night; -- Harborlight, the window ending tonight: good_30d 685, total_30d 720, rolling_sli 0.9514
★ Step 2 · the nightly distribution and the p50 night select percentile_cont(0.5) within group (order by good / total::float) as p50_night, min(good / total::float) as worst_night, sum(good) / sum(total)::float as the_month from nightly where night >= dateadd('day', -30, current_date); -- Harborlight: p50_night 1.0000 (24 of 24), worst_night 0.4167 (night 9, 10 of 24), the_month 0.9514 -- The p50 night clears 99.9. The month does not clear 96.
★ Step 3 · the budget in partitions select target, (1 - target) * 720 as budget_partitions from (values (0.95), (0.97), (0.99), (0.999)) as t(target); -- 0.95 -> 36 · 0.97 -> 21.6 · 0.99 -> 7.2 · 0.999 -> 0.72
★ Step 4 · the night each budget is first exceeded with running as ( select night, total - good as bad, sum(total - good) over (order by night) as cum_bad from nightly where night >= dateadd('day', -30, current_date) ), targets as ( select * from (values (0.95), (0.97), (0.99), (0.999)) as t(target) ) select t.target, (1 - t.target) * 720 as budget, min(r.night) filter (where r.cum_bad > (1 - t.target) * 720) as exhausted_on, greatest(0, (1 - t.target) * 720 - max(r.cum_bad)) / ((1 - t.target) * 720) as budget_left from targets t cross join running r group by t.target order by t.target; -- 0.95 budget 36 exhausted_on null budget_left 0.028 (3 percent, one partition) -- 0.97 budget 21.6 exhausted_on night 15 budget_left 0 -- 0.99 budget 7.2 exhausted_on night 9 budget_left 0 -- 0.999 budget 0.72 exhausted_on night 4 budget_left 0
★ Step 5 · the line in the contract insert into ops.slo_contract (pipeline, indicator, target, window_days, signed_on, review_on, note) values ('orders', 'partition fresh within 60 min, reconciled, all shards', 0.95, 30, current_date, dateadd('month', 3, current_date), 'history supports 95.14; move to 0.97 once the coverage check has run a quarter and the connector retry is in');

Do not write the alert tonight. The target decides the budget; the alert policy decides the pages, and they are separate levers. Session 3 spends this budget hour by hour and shows that the page count does not move when the target does.

Homework

Before session 3

30 min
  1. Run the rolling 30-day query over your own 90 days and write down three numbers: the best window, the worst window and the median. The target goes below the median, and the gap to the worst is the risk you are accepting.
  2. Compute the exhaustion night for your four candidates against your own last thirty nights. If none of them survives to night 30, the loose target is looser than you thought, and that is the finding.
  3. Write the contract line, including the review date and the two conditions for tightening. Read it to the person who signs the report and note what they push back on.
  4. Bring the incident list from session 1's homework. Session 3 pages on it, and the number of pages depends on how the bad partitions cluster, not on how many there are.
Check yourself

Three questions

Twenty-five of Harborlight's last thirty nights landed all 24 partitions, so the median night is at or above 99.9 percent. Why is 99.9 percent the wrong monthly target?

The month is the area under all thirty bars, not the height of the middle one. The month achieved 95.14; any target above that is a promise the last thirty nights already broke.

"Don't pick based on current performance" and "read the history before you write the target" appear to contradict each other. How do they fit together?

Harborlight's best recent month was 99.6 during a babysat migration. Its typical month is around 95 to 96. The guidance points at a target under 95.14 and warns against 99.6.

Why is a 95 percent promise the pipeline keeps worth more to the settlement team than a 99 percent promise it breaks on night 9?

A kept 95 lets the reader build a morning check that tolerates one bad partition in twenty. A broken 99 sends them to build a shadow process. And the page count is set by the alert policy, not the target.

Sources covered

What tonight maps to

✓ SRE book, Service Level Objectives - choosing the target Don't pick based on current performance, keep it simple, avoid absolutes, as few SLOs as possible, perfection can wait: start loose and tighten. Each applied to the 95 / 97 / 99 / 99.9 candidates.
✓ SRE workbook, Implementing SLOs - error budget as 100 percent minus the SLO Computed in partitions at four targets over 720 events, with the exhaustion night for each from the frozen month.
✓ Percentiles of history as the input to a target Rolling 30-day windows over 90 days, the nightly distribution, and why the p50 night is the trap rather than the answer.
◐ Spending the budget hour by hour, and paging on burn rate Session 3. Tonight the budget only decides which night the promise breaks.
◐ Weighting bad partitions by impact Every bad partition counts the same here. A corrupt total is worse than a late one, and a mature budget knows it; session 8 names it as the first extension.
· How a bad partition is detected Not covered by design. The data observability course owns detection; here a bad partition only has to be counted.

Session 2 cheat sheet

Indicator first, target secondA target set before the indicator exists is a target on nothing.
Below the typical monthRead the history for what the pipeline does without heroics; set the target under it, never at the best month.
Budget = (1 - target) x 72036 at 95, 21.6 at 97, 7.2 at 99, 0.72 at 99.9.
Exhaustion nights95 never, 97 on night 15, 99 on night 9, 99.9 on night 4. Same curve, different line.
The 99.9 trapThe p50 night promised for every night. Less than one bad partition allowed; the first incident breaks it.
Kept beats tightA kept 95 lets the reader plan. A 99 broken on night 9 tells them nothing after.
Tighten on a dateQuarterly review, after the fix has run a quarter. One step at a time, 95 to 97.
Rolling, not calendarA calendar month resets on the first and teaches everybody to ship on the second.