A Cutoff Rule for Automation Events Arriving Out of Order
Automations that track shipments often receive messages in a different order from the one in which things happened. A courier scan taken at 09:10 may reach your system after a scan taken at 11:40. If the automation simply writes whatever arrives last, an order that is already delivered can slide back to in transit. This article proposes a small ledger and a decision table you could adopt to apply a late status without reverting a newer one. Everything here is a design suggestion to adapt, not a description of any existing tool.
Start with two clocks
Each incoming event carries, or could be given, two times. The occurred time is when the carrier says the thing happened. The received time is when your automation saw it. Precedence should be judged mainly on occurred time and a state rank, while received time is kept for audit. If a source gives no occurred time, treat that as a flag, not as permission to use received time silently.
The event precedence ledger
Keep one row per event, never overwritten. A suggested set of columns:
- event_id: the source identifier, or a hash of shipment, status and occurred time
- shipment_ref
- status
- state_rank: a number you assign, for example created 10, handed to carrier 20, in transit 30, out for delivery 40, delivered 50, exception 35 (reviewed separately)
- occurred_at
- received_at
- decision: applied, recorded only, held for review, or duplicate
- reason: one short phrase
The shipment also has one current row holding the state that the customer-facing view uses. The ledger is the history; the current row is a conclusion drawn from it.
The cutoff rule
Compare the incoming event with the current state on both occurred_at and state_rank.
- Newer occurred_at and equal or higher rank: apply.
- Older occurred_at and lower rank: record only. It is true history but no longer the present.
- Older occurred_at and higher rank: held for review. The clocks disagree, which may mean a clock error or a real return to an earlier stage.
- Newer occurred_at and lower rank: held for review, unless your team has defined that status as a legitimate step back, such as a failed delivery attempt.
- Same event_id already in the ledger: duplicate, no change.
- Missing occurred_at: record, hold, and do not apply.
You may also set a tolerance, say a few minutes, within which two occurred times count as equal, so that rank decides. Choose the value from how your own sources behave.
Hypothetical worked example
Shipment A-17 is currently out for delivery (rank 40, occurred 10:05). Three messages arrive:
- In transit, occurred 08:30. Older and lower rank, so record only. The current state stays.
- Delivered, occurred 12:20. Newer and higher rank, so apply. The current state becomes delivered.
- Out for delivery, occurred 10:05, same event_id as the existing row. Duplicate, nothing changes.
A fourth message then arrives: In transit, occurred 13:00, after delivery. Newer time but lower rank, so it is held for review. A person decides whether it is a data fault or a genuine reroute.
Branching choices
If your carriers supply reliable occurred times, lean on them and keep rank as a tiebreaker. If they are unreliable, lean on rank and hold more cases for review. If exceptions are common, give them a lane of their own rather than forcing them into the linear ranking.
Stop conditions
Pause automatic applying and move to review when held events pile up beyond a number your team can clear in a day, when many events lack occurred times, or when one source suddenly produces a run of rank reversals. That pattern points to a mapping or clock fault, not to a lot of unusual shipments.
Acceptance checks
- Replay the worked example in a scratch copy in every arrival order; the final state should always be delivered, except for the held fourth message.
- Replay the same event twice; the ledger should gain no applied row.
- Check that no applied row ever has a lower rank than the state it replaced without a recorded reason.
- Confirm every held event has an owner and a reason.
- Confirm the ledger can reconstruct the current state from scratch.
A rule like this does not make late data correct. It makes the choices visible, so a delayed message is stored honestly and cannot quietly rewrite what is already known.