What Can the System Know at Decision Time?
A reading can describe an earlier event and still arrive too late. Design a data contract that respects both clocks.
14 sections · 4 questions · 1 coding challenge
The arrow keys move between sections too.
A Model Inherits Its Data Dependencies
BOTIE
Our two-clock example makes one such dependency explicit. Event time describes the measurement; availability time describes when our service could use it. These invented timestamps are a teaching contract, not a guarantee that every database preserves the history needed to reconstruct them.
Sources for this history
The Reading Existed. Botie Still Had Not Received It.
At minute 10, Botie must decide whether to inspect a pump. One sensor recorded a vibration spike at minute 8, but its network connection delayed the message until minute 12. A historical table now contains that spike. The running system could not have used it at minute 10.
This distinction also affects software. A support article may have been written yesterday but added to a search index only this afternoon. We need to design around the information the service could actually retrieve.
Times are minutes on the same clock. Values equal to the cutoff are eligible in this example.
Step 1 of 2
Read both timestamps
Compare each record with the decision at minute 10. An earlier event does not undo a later arrival.
| Record | Event time | Available time | Eligible at 10? |
|---|---|---|---|
| A | 8 | 9 | Yes |
| B | 8 | 12 | No |
| C | 11 | 11 | No |
A
- Event time
- 8
- Available time
- 9
- Eligible at 10?
- Yes
B
- Event time
- 8
- Available time
- 12
- Eligible at 10?
- No
C
- Event time
- 11
- Available time
- 11
- Eligible at 10?
- No
Step 2 of 2
Preserve the boundary through the pipeline
A retrieved record still needs its meaning checked before a model consumes it.
- 1
Receive
Keep event and arrival timestamps - 2
Validate
Check units, identity, and schema - 3
Select
Use records available by the decision time - 4
Predict
Save the input contract and model version
Reconstruct the information Botie actually had
The comparisons preserve each record’s position, so multiplying joins the two conditions for that same record.
Which readings were available for this decision?
Move the decision time or delay a record. Both clocks must be at or before the decision.
BOTIE
Eligibility mask, one entry per record
- 01
- 10
- 20
Follow the operations
1. Decision time
10
2. Event time per reading
- 08
- 18
- 211
3. Threshold gate
- 01
- 11
- 20
4. Availability time per reading
- 09
- 112
- 211
5. Threshold gate
- 01
- 10
- 20
6. Multiply
- 01
- 10
- 20
7. Result
- 01
- 10
- 20
This assumes a common clock and trustworthy timestamp history. Freshness, permissions, and measurement quality need additional checks.
1. An event and its arrival are different facts
A sensor samples the world at one time and delivers the record at another. Clocks, buffering, and network interruptions can separate them. For an offline training table, the delay is easy to overlook because all the records are now present.
A decision-time reconstruction needs the timestamp when the consuming system could actually access the record. If a later repair changes a historical value, preserve the earlier version too. The final corrected table may describe a different information state.
Document which clock each timestamp uses and how clock disagreement is handled. A precise-looking timestamp is not proof of a synchronised clock.
2. Describe an input with more than its name
A field called temperature could mean Celsius, Fahrenheit, or a moving average calculated over a window. A feature contract should state units, shape, missing-value behaviour, and the aggregation window. It should also say which entity the record describes.
For text retrieval, include when a document version entered the index and what permissions the requester had. The existence of a document somewhere does not mean this request could retrieve it.
These are interface requirements. A fitted model cannot reliably repair a changed meaning that the pipeline does not identify.
3. Build the eligibility check from two comparisons
Start with two yes-or-no questions for each record. Did its event happen by the cutoff? Was the record available by the cutoff? Both must hold. We use inclusive comparisons, so a record available exactly at the decision time is accepted.
In the workshop, a Threshold gate reports 1 when its first input reaches its second. Connect the cutoff to the Score input and the record timestamps to Cutoff. This tests whether the decision time has reached each timestamp. Multiplying the two binary masks implements “both”.
Event times = [8, 8, 11]
Availability times = [9, 12, 11]
Decision time = 10
Event-time mask = [1, 1, 0]
Availability mask = [1, 0, 0]
Eligible = [1, 1, 0] × [1, 0, 0] = [1, 0, 0]The labels on the wires matter. Reversing a comparison would admit future information.
A boolean mask keeps record identities aligned
Comparison produces a boolean array of the same shape. Selection uses its True positions.
import numpy as np
arrival = np.array([4, 9, 6])
reading = np.array([20., 99., 24.])
known = arrival <= 6
print(known.tolist())
print(reading[known].tolist())[True, False, True]
[20.0, 24.0]This program demonstrates only the arrival check. The challenge also enforces event time and a valid timestamp order.
Check yourself
Questions on Parts 1 to 3
Question 1 of 2
May the decision use this record?
Use the information below.
Decision time is 10. A record has event time 8 and availability time 12.4. Eligibility does not mean freshness
A reading from last week can pass both comparisons. That does not make it a useful description of a pump now. Add a maximum permitted age when the task requires recent evidence, and say which timestamp the age uses.
Do not confuse a freshly delivered old reading with a fresh measurement. A freshness check usually needs event time. A separate transport monitor can detect long delivery delays.
The workshop deliberately checks eligibility alone. A complete pump service would also choose a freshness rule and a response when no acceptable reading remains.
5. Labels have an availability time too
A fault may happen after the prediction and be confirmed several days later. The outcome window tells us what we want to predict. Label availability tells us when we can train or evaluate using the confirmed result.
For a retrospective training simulation, include only labels that would have been known at that training date. A final dataset with every later confirmation can overstate how quickly the system could have adapted.
Keep the prediction identity so a later outcome can be joined to the correct earlier decision. An outcome must never be inserted into its own input features.
6. Make missing information an explicit branch
If no eligible reading exists, the pipeline needs a response. It might request a manual check or keep using a previous reading within a defined age limit. Filling a missing value with zero quietly assigns a numerical meaning to absence.
Record the branch taken so later evaluation includes the cases where the model could not run. Reporting accuracy only on successfully served cases hides coverage failures.
Our reusable Python function returns an eligibility mask. The caller can then decide how to select records or handle an all-False result without pretending the evidence existed.
7. Test the boundary itself
Include records just before the cutoff, exactly at it, and just after it. Include a record with an early event and a late arrival. Those cases exercise the design rule more directly than a large random table.
This lesson assumes arrival cannot precede the event on our shared clock. A violation raises an error. Real systems with uncertain clocks may need an explicit tolerance or interval model instead of silently accepting impossible ordering.
A contract is useful when another component can test it. The challenge’s invalid-input behaviour is part of that contract.
Check yourself
Questions on Parts 1 to 7
Question 1 of 2
What does the two-clock check establish?
Use the information below.
A record has event time 2, arrival time 3, and decision time 100. No maximum age is specified.Try it with Botie
Build with Botie
Write and run Python