Decide what a failed check does
A check with no authority is a signal: it reports. A gate is a check that can stop something. The action space has four levels, not two (warn, quarantine, block, restate), and the level is a property of the check, chosen by one cost comparison: block when the cost of bad data downstream is greater than the cost of no data downstream. Which level should this check have?
You will end with the action this check takes when it fails, what that action costs, and who pays it.
Decide
For the consumer that matters most, is bad data worse than no data?
A regulatory submission: yes. A recommendation feed, where stale-but-present beats absent: no.
Why
The comparison is per consumer, but the gate sits at the producer. A dataset that feeds both a compliance report and a dashboard cannot have a correct level for both; that is a reason to split it, or to agree a contract, not to pick a level by habit.
Can the failure be confined to one partition, such as one region or one day?
Can the failing records be set aside, and their share published next to the data?
YesQuarantine
NoWarn
Where you can land
Warn
Use it when bad data is cheaper than no data, and the failing records cannot be separated.
What it costs: nothing is stopped and nobody is told. Consumers who care start re-checking on their own side, duplicate the work, and drift apart on what "good" means.
Quarantine
Use it when bad data is cheaper than no data, and the bad records can be set aside.
What it costs: an outage is traded for an invisible bias, because bad records are never a random sample. In one batch, 1% of orders failed to parse, but they were the largest baskets: 4.2% of revenue went missing and the published average was 3.2% low.
Before you build it
Publish the quarantine rate where the data is read
Publish it as a property of the dataset, at the granularity consumers aggregate by: if they read by region, the rate by region. Treat quarantined records older than a few weeks as an archive, not a backlog: the schema and code needed to reprocess them have moved on.
Block the partition
Use it when bad data is worse than no data, and the failure is local.
What it costs: a single verdict for the dataset; in return, one bad region or day stops while the rest flows. This is bulkheading applied to correctness.
Block the dataset
Use it when bad data is worse than no data everywhere.
What it costs: no data downstream until it is fixed, and a backlog, because a pipeline can stop processing but not arrival. A stop of T hours at utilization u takes T × u ÷ (1 − u) hours to drain: six hours costs 9 hours of catch-up at 60% utilization and 54 at 90%.
Before you build it
Make publication the last, atomic step
Write to a hidden place, audit, then switch a pointer (write-audit-publish). A data deploy cannot be rolled back once consumers have read it. A stream has no publication point, so its only dataset-level gate is a circuit breaker on the flow.
Check the stop against your spare capacity
The safe stop duration is bounded by provisioned over-capacity. If utilization is high, the restart is itself an incident: a backlog burst whose recovery load can re-trigger the failure.
Restate
Use it when the wrong value has already been read.
What it costs: three things, or the correction reaches nobody. The old answer must still be addressable (a kept table version or snapshot), the readers must be found (lineage and usage), and the correction must say what kind it is: a silent fix for a dashboard everyone re-reads, a published correction wherever the number has left the team.