Data Quality Guide

Data quality SLAs: what to promise, and what it costs to keep

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

An SLI is what you measure, an SLO is the target you aim at, and an SLA is what happens when you miss. Most data teams write the third without ever computing the first, then discover that the number they promised was never achievable. The sequence that works runs the other way: measure for a quarter, set the objective just inside what you already achieve, and only then write the agreement.

7 min readFor data product owners writing the service level section of a contract

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

169/20003 credits left
Try:

No account needed · Editable canvas, not a picture

Three words that are not synonyms

The indicator (SLI) is a measurement with a definition precise enough that two people compute the same number: minutes between the newest placed_at value and the current time, sampled at the output port every fifteen minutes. Ambiguity here poisons everything downstream, because a freshness measured at load start and one measured at commit differ by exactly the duration of the load.

The objective (SLO) is the target for that indicator over a window: freshness under two hours for 99 percent of measurements in a rolling thirty days. Note the two numbers. A target without a window and a percentile is a wish, since any threshold is met sometimes.

The agreement (SLA) is the consequence: who is told, how fast, what the fallback is, and what the producer commits to doing. Inside one company there are rarely financial penalties, so the meaningful content is the escalation path and the remediation commitment. An SLA with no consequence section is an SLO with a formal tone.

The four indicators worth committing to

Freshness: the age of the newest record at the output port. It is the indicator consumers notice first and the one that most often has a real business deadline behind it, such as a report that must be right by 9am.

Completeness: the share of expected records present, measured against a countable expectation such as the source row count or a known daily range. Vaguer than freshness, so define the expectation explicitly or do not commit to it.

Correctness: the pass rate of a named, versioned set of quality checks. The trick is that the check set has to be named in the agreement, because "the data is correct" is unmeasurable while "these eleven checks pass" is not.

Availability: the output port responding and queryable. Usually inherited from the platform rather than owned by the domain, which is worth stating so the domain is not held to a warehouse outage.

How to pick the number

Measure first, for at least thirty days and preferably ninety, with no target set. You need the shape of the distribution, not the average: batch pipelines are heavily tailed, and the mean load time tells you almost nothing about the bad Monday.

Set the objective at roughly the observed p95, then round to something a human can remember. If ninety-five percent of loads land within ninety-four minutes, promise two hours. Promising the observed best case guarantees a miss in the first month and teaches consumers that the number is decorative.

Give yourself an error budget and compute it rather than feeling it. Sampling every fifteen minutes for thirty days is 2,880 measurements; a 99 percent objective allows 28 of them to be out of target, and since each failing sample stands for a fifteen-minute window that is about seven hours of lateness across the month. Seven hours sounds generous until a single stuck load consumes five of them in one morning. When the budget is spent, reliability work takes priority over the next feature; when it is never touched, the target is too loose and can be tightened. Without the budget, every individual miss becomes an argument.

Set the objective per output port, not per product. The Kafka topic and the warehouse table for the same product have genuinely different latencies, and one number covering both will either be dishonest about one or too loose for the other.

Writing it down where it will be read

The service level belongs in the data contract, next to the schema, and travels through the same pull request as the code that has to keep it. Service levels stored in a wiki page drift within a quarter, for the same reason contracts stored in a separate repository do.

Publish the measurement alongside the promise. A dashboard showing the indicator against the objective for the last thirty days ends most of the disputes before they start, because the disagreement is usually about what actually happened rather than about what was promised.

Keep the notice period separate from the SLA. Freshness and completeness are about the running system; the notice period before a breaking change is about the contract's evolution. Both live in the contract, and confusing them leads to a schema change being announced as an incident.

-- The SLI, defined so two people compute the same number.
-- Measured at the output port, on the business timestamp, not on load time.
select
  datediff('minute', max(placed_at), current_timestamp()) as freshness_minutes
from analytics.checkout.orders_fct;

-- The SLO over the window, from the samples you have been storing.
-- One row per 15-minute probe of the query above.
select
  count(*)                                            as samples,
  count_if(freshness_minutes <= 120)                  as within_target,
  round(100.0 * count_if(freshness_minutes <= 120)
        / count(*), 2)                                as attainment_pct,
  count_if(freshness_minutes > 120)                   as budget_spent,
  greatest(0, floor(count(*) * 0.01)
              - count_if(freshness_minutes > 120))    as budget_left
from platform.sli.freshness_samples
where port = 'snowflake://analytics/checkout/orders_fct'
  and measured_at >= dateadd('day', -30, current_timestamp());

The map you need when the budget is burning

A missed freshness target is a question about what is downstream. Generating the diagram from the connected repository on a daily sync, with column-level lineage on the canvas, means the answer is on screen rather than reconstructed under pressure.

FAQ

What is a data SLA?

A written agreement between a data producer and its consumers covering what is promised (freshness, completeness, correctness, availability), over what window, and what happens when the promise is missed: who is notified, how quickly, and what the producer commits to doing. Inside one company the consequence is usually escalation and remediation rather than a financial penalty.

What is the difference between SLI, SLO and SLA for data?

The SLI is the measurement, such as minutes between the newest record and now, sampled at the output port. The SLO is the target for that measurement over a window, such as under two hours for 99 percent of samples in a rolling thirty days. The SLA is the agreement about consequences when the SLO is missed.

How do you set a data freshness SLA?

Measure freshness for thirty to ninety days with no target, look at the distribution rather than the average, then set the objective near the observed p95 and round it to a memorable number. Promising the observed best case guarantees an early miss and trains consumers to ignore the figure.

Should the SLA live in the data contract?

Yes, in the service levels section, next to the schema, versioned in the producer repository so it travels through the same pull request as the code that has to keep it. Service levels kept in a separate wiki page drift out of step within a quarter.

What is an error budget for a data pipeline?

The allowed shortfall implied by the objective. Sampling freshness every fifteen minutes for thirty days gives 2,880 measurements, so a 99 percent target allows 28 of them to miss, which is roughly seven hours of lateness across the month. Spending the budget makes reliability work the priority; never touching it means the target is too loose and can be tightened.