Back to blogDeutsche Version
AI Automation

Late Sensor Data: Decide When Industrial Features May Be Final

Separate initial feature results, late corrections and online finalization. A Flink event-time walkthrough with explicit window boundaries, reconnect tests and a control-action boundary.

10 min readUpdated
Dark technical cutaway of a brass sampling carousel and red shutter, with a delayed cyan sensor sample approaching the closing chamber. Text: INDUSTRIAL AI — WHEN IS YOUR DATA FINAL?

BLUF: An industrial feature window is not complete merely because its first result exists. Define when the result is provisional, how long late observations may revise it, and when the online correction path closes. In Apache Flink, watermarks, allowed lateness and idle-input detection solve different parts of that contract. None proves that every sensor observation arrived. Keep retrospective feature corrections separate from permission to repeat a maintenance or physical-control action.

This walkthrough uses five-minute tumbling event-time windows, a twenty-second out-of-order bound, one-minute idleness detection and two minutes of allowed lateness as illustrative settings—not recommended plant defaults. API and millisecond boundary references are pinned to Flink 2.1.1. That is a reproducible documentation baseline, not a claim that it is the current release or a deployment recommendation. Validate the equivalent behavior on your supported runtime and connector before rollout.

Start with two clocks and one decision

A sensor event needs a trustworthy source timestamp and a separately retained arrival timestamp. Source time selects the feature window; arrival time establishes when the platform could have known the observation. Replacing source time with reconnect time makes an old vibration burst appear to describe the machine now. Replacing arrival time with source time makes a historical reconstruction falsely claim that delayed information was already available.

The existing passive OT observability contract covers timestamp provenance, clock uncertainty and acquisition quality. Apply those checks before watermark generation. A bad future timestamp can advance event-time progress and prematurely close unrelated windows; retaining an uncertainty flag after aggregation is too late. Quarantine unacceptable timestamps using a documented source-quality policy rather than silently clamping them to the ingest clock.

Specify the decision separately: “Produce a five-minute bearing-temperature mean for advisory maintenance, publish an initial estimate promptly, accept bounded corrections, and retain older backfill for offline reconciliation.” An arithmetic mean is used here to make outputs inspectable. Irregular sampling may instead require a time-weighted statistic and a different gap policy; the example does not establish that a sample mean is a good maintenance feature.

Three timing controls, three different consequences

Flink's event-time model describes watermarks as progress declarations. For the pinned bounded-out-of-orderness generator, a periodic emission uses maximum observed event timestamp minus the configured bound minus one millisecond. Emission scheduling adds delay. This is not a wall-clock deadline, and an inactive stream cannot create new event-time evidence merely by waiting.

An operator receiving parallel inputs progresses with their minimum watermark, excluding inputs marked idle. The watermark strategy documentation recommends assigning the strategy at the source where partition or split knowledge is available. Do not assume a strategy attached after a merged stream can distinguish every quiet Kafka partition. Verify the deployed connector's split-level behavior.

Allowed lateness is different from the out-of-order bound. It retains eligible event-time window state after the initial firing, so accepted late observations can change an already-emitted result. The default allowed lateness is zero. With the default event-time trigger and retained state, an accepted late element can cause another firing. These are replacement results for the same logical feature window, not additional independent measurements.

Idleness detection prevents a silent input from holding back otherwise active inputs indefinitely. It does not certify that the quiet source has finished its history. A returning partition may deliver observations behind the downstream watermark, which does not rewind. If every input becomes idle, do not assume all remaining windows automatically become final. Event-time completion and operational freshness need separate signals.

Decision table: the window lifecycle

For the example interval [12:00:00.000, 12:05:00.000), the final included millisecond is 12:04:59.999. With two minutes of allowed lateness, cleanup is at 12:06:59.999. The exact comparisons below follow the pinned implementation, not rounded wall-clock descriptions.

ConditionWindow behaviorFeature-store contractConsumer action
Watermark below 12:04:59.999Default trigger has not firedNo initial result yetShow waiting or stale; never infer a zero
Watermark reaches 12:04:59.999Initial event-time firingUpsert revision 1 as provisionalAdvisory use only within freshness and coverage policy
Late event arrives before cleanupRetained aggregate can fire againUpsert a higher revision of the same keyRefresh evidence; do not replay a physical action
Watermark reaches 12:06:59.999Window state is cleaned upClose online corrections under the declared policyDo not mistake state cleanup for a new final-result message
Event arrives at or after cleanupToo late for this windowPersist side-output evidence for reconciliationKeep offline backfill outside the live command path
Input is marked idle then returnsOther inputs may already have advanced progressRecord excluded-source coverage and late countsReassess evidence quality; watermark cannot rewind

The window documentation explains lifecycle, late firings and side outputs. The default trigger does not automatically emit a separate “final” feature at cleanup. If consumers require that marker, implement it explicitly: for example, a keyed downstream materializer retains the latest revision and uses an event-time timer at the policy boundary. Test ordering when a watermark jumps across both initial firing and cleanup. Do not add a processing-time sleep and label its expiry evidence completeness.

Diagram: event time is not arrival order

Synthetic arrival timeline for one event-time window: initial mean 15, late correction to 20, cleanup at 12:06:59.999, then backfill to reconciliation only.

The diagram describes one synthetic window. A third sample belongs to the old window even though it arrives after the first result. A fourth belongs to that same event-time interval but arrives after cleanup; its only automatic destination is the reconciliation path. The highlighted boundary is a policy cutoff, not proof of full source coverage.

1. Validate the input envelope. Retain asset lifecycle ID, sensor ID, event ID or source sequence, event-time milliseconds, arrival time, value, unit, quality and clock provenance. Deduplicate retransmissions before aggregation using a retention policy that covers the accepted replay horizon. Exactly-once checkpointing does not remove two genuinely delivered source records representing the same measurement.

2. Configure WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(20)), extract the validated source timestamp with withTimestampAssigner, and add withIdleness(Duration.ofMinutes(1)). Pass the strategy into the connector source where supported. The twenty seconds describes event-time disorder, not “accept anything arriving within twenty seconds of now.” Exercise quiet splits as well as quiet whole subtasks.

3. Key by the feature identity, including the asset lifecycle and sensor or declared sensor group. Use TumblingEventTimeWindows.of(Duration.ofMinutes(5)), allowedLateness(Duration.ofMinutes(2)) and sideOutputLateData with a typed OutputTag. Aggregate count and sum, then attach the window boundaries and contract metadata through an AggregateFunction plus ProcessWindowFunction. These are documented API building blocks, not a complete compiled job supplied by this article.

4. Consume getSideOutput with the same tag and persist late records to a governed reconciliation sink. Merely declaring a side output does not create durable storage. Include reason, source identity, original event time, arrival time and feature-contract version. Monitor successful persistence and sink failures separately from the operator's default dropped-record metric: a record routed to a side output is not necessarily counted as a dropped record.

5. Upsert into the feature store under a stable key such as asset lifecycle, sensor, feature definition version and window start/end. Include revision, sample count, watermark at emission, quality/coverage summary, status and materialized_at. Reject older revisions in the sink. Make revision generation checkpoint-consistent or derive deterministic update identities; a process-local counter is unsafe after recovery. Do not add a corrected full-window mean to an earlier mean as if both were new observations.

6. Separate finalization from action. A finalization service must consume the correct watermark progression and retain enough state to update the latest revision's status. Keep action approval and idempotency records in a separate durable decision ledger. A new data revision may request review; it must not automatically create another work order, reissue a shutdown or revoke an already executed physical action.

Reconnect and backfill fixture with exact outputs

Use UTC timestamps, distinct event IDs and one sensor in one window. Feed the following operations in arrival order. Watermarks are explicit test inputs; a real source's emission schedule is a separate integration test. The small policy fixture executed for this article models aggregate retention, default late re-firing, cleanup and side routing. It is not a Flink cluster, connector or checkpoint test, and makes no throughput claim.

Arrival-order operationExpected main outputExpected late side output
A: event 12:00:10, value 10NoneNone
B: event 12:04:50, value 20NoneNone
Watermark 12:04:59.999Revision 1: count 2, sum 30, mean 15None
C: reconnect event 12:03:00, value 30Revision 2: count 3, sum 60, mean 20None
Watermark 12:06:59.998No additional resultNone
Watermark 12:06:59.999No final-result message; clear window stateNone
D: backfill event 12:02:00, value 40No change to the materialized mean 20D retained for reconciliation

Also test the exact cleanup boundary with a fresh fixture: C arriving at watermark 12:06:59.998 is accepted; at 12:06:59.999 it is side-routed. Keep those as independent runs so a prior accepted C cannot conceal the boundary condition. Replay the same event ID to prove deduplication and replay an older sink revision to prove stale-update rejection.

For idleness, give active partition A watermark 12:04:59.999 and quiet partition B watermark 12:03:00.000. Before B is declared idle, the combined watermark remains 12:03:00.000 and the window has not fired. After B is excluded, A can trigger the initial result. When B returns, the downstream watermark must not decrease; classify its samples against the existing cleanup boundary. Our policy test checks this minimum/exclusion rule. Connector timeout scheduling and recovery still require a runtime test.

The executed policy suite has six deterministic cases: reconnect/backfill, last accepted millisecond, exact cleanup rejection, idle-input exclusion without rewind, input deduplication, and stale revision rejection. These synthetic checks validate the proposed contract, not a production latency or reliability result. The pinned WindowOperator implementation grounds the cleanup comparison; the bounded watermark generator grounds the one-millisecond offset.

Choose budgets from decision cost, not convenience

Longer disorder bounds delay initial results. Longer allowed lateness retains more state and produces more corrections. Shorter idleness timeouts restore progress faster but can exclude legitimately quiet equipment. Large reconnect bursts stress both the state backend and correction sink. An incremental sum/count aggregate limits per-window payload, but many keys, overlapping windows, deduplication entries and finalization timers still consume resources. No universal safe setting follows from this example.

Measure source-to-arrival delay, operator watermark lag, age of the newest usable feature, per-source coverage, correction counts, too-late counts and reconciliation-sink failures. Report denominators and observation periods when comparing lateness rates. A low correction rate can mean good timing—or silent loss upstream. Treat missing expected samples and idle exclusions as explicit quality evidence, not a successful zero.

A retrospective rebuild should write a separately versioned reconciled view. Preserve the value and revision actually served at the original decision time. This is the bridge to availability-aware predictive-maintenance backtests: a corrected feature computed tomorrow must not silently replace what yesterday's model could know. After the timing contract is sound, digital-twin drift validation can assess disagreement without confusing delayed windows with physical drift.

Release checklist and next decision

Require a named owner for timing budgets; validated source clocks; a pinned runtime and connector; explicit initial/correction/final states; verified upsert and deduplication behavior; persisted late evidence; coverage and freshness limits; reconnect, idle, boundary and recovery tests; and a decision ledger that cannot replay physical actions from data corrections. Run checkpoint/restore, all-inputs-idle, clock-jump and sink-outage cases on the actual deployment before production approval.

For a focused architecture review, bring one asset class, one feature definition and a representative reconnect trace. I can help turn these into a lateness budget, executable acceptance matrix and feature-consumer contract. The first deliverable should be an agreed answer to “When may this value change, and what is allowed to happen when it does?”—before a model consumes it.

#enterprise-ai#industrial-ai

Building AI into your operations?

I help teams design and ship compliant AI automation — production agents with n8n and LangGraph, RAG systems, and the evals to keep them reliable.

A

Written by

Ade Christanto

AI Automation Specialist and former network engineer focused on practical AI implementation for German B2B and Mittelstand companies.