The Message Engine
What decides a message needs sending — trigger types, message segments, and the compile-then-deliver lifecycle.
The Message Engine is the service object that decides when something needs to be said. It evaluates message definitions, builds the message content, and hands the result to notification servers for delivery.
Understanding the split matters when troubleshooting: the Message Engine decides whether and what, a notification server handles how it gets there. A message that was never composed and a message that failed to deliver are different problems.
Message triggers#
A message definition fires on one of five trigger types:
| Trigger | Fires when |
|---|---|
| Time Period Started | A period begins |
| Time Period Ended | A period completes |
| Event Period Started | An event begins |
| Event Period Ended | An event completes |
| Measure Limit Exceeded | A measure breaches a limit |
Choosing correctly is most of the design.
Measure Limit Exceeded is the alarm case: a value has gone out of range and someone should act. It depends entirely on the limit being set at a threshold where action is genuinely warranted. See Measure Limits and Thresholds.
Time Period Ended is the summary case, and is the right trigger for most routine communication: a shift summary when the shift closes, a daily report when the day completes. It fires on a complete period, so the numbers in it are final.
Time Period Started suits a message that opens a period — a shift's targets at handover.
Event Period Ended is the most under-used of the five. It fires when an event completes, which means a message can carry the whole event's outcome: a batch finished, with its yield and quality result; a stoppage ended, with its duration and reason; a CIP cycle completed, with whether it passed.
Event Period Ended is often what people actually want. "Tell me when a batch finishes and how it went" is a single message definition on this trigger. Built instead as a limit on a measure, it is awkward and fires at the wrong moment. If the thing you want to report on has a start and an end, this is the trigger.
Period Ended means "after the period", not "at the end of it". A message on Time Period Ended fires once the period's values are available. If a source delivers late or a long aggregation chain has not finished, the message is later than the wall clock might suggest. That is correct behaviour — the alternative would be a summary with gaps — but it means a shift summary is not a punctual thing. Do not build a process that assumes it arrives at exactly 06:00.
Message segments#
A message is composed of segments rather than being a single block of text. Each segment contributes a piece of content:
| Segment type | Contributes |
|---|---|
| Text | Fixed wording |
| Measure Value | A measure's value, formatted, with its limit status |
| Measure Attribute Value | An attribute value in the measure's context |
| Event Period | The event itself — its identity and timing |
| Event Period Attribute | An attribute of the event |
| Event Period Value | A value associated with the event |
| Report | A report, included in the message |
| Dashboard | A dashboard, included in the message |
So a shift summary is a sequence: some text, a production figure, some more text, an availability figure, and a dashboard. Assembled from segments rather than written as a template with placeholders.
Two consequences worth knowing.
Measure Value segments carry their formatting and limit status. The number appears with the measure's format string applied, and its limit state travels with it — which is what lets a message convey whether a value was acceptable, not just what it was. This is another reason to set formats and units on measures rather than overriding them elsewhere.
Report and Dashboard segments are how visual content gets into a message. A shift summary can carry the actual dashboard, not just a link to it, which matters for recipients who read notifications on a phone and will not log in.
The message lifecycle#
A message moves through states, and knowing them makes diagnosis quick:
| Status | Meaning |
|---|---|
| Compiling | The engine is assembling the content |
| Compiled | Content is built and ready to deliver |
| Processed | Handed to the notification server and sent |
| Failed | Something went wrong |
The useful distinction is between Compiled and Processed. A message stuck at Compiled was successfully composed but not delivered — so the problem is the notification server, its credentials, or its network path. A message that Failed during compilation could not be built, which points at the definition itself: a segment referencing a measure with no value, a report that cannot render, a missing dependency.
Check the status before changing anything. When someone reports missing notifications, look at the message status first. It splits the problem in half immediately, and it prevents the common waste of reconfiguring an email server when the message was never composed.
Deployment#
The Message Engine is a service object on a Platform, hosted by Flow Bootstrap. Like everything else, it must be deployed to run, and a configured-but-undeployed Message Engine produces exactly the symptom of "no notifications at all, no errors".
It also needs the notification servers it hands messages to be deployed. Both halves must be running.
See Infohub Architecture at a Glance and Deploying Configuration.
Multiple periods in one message — shift totals in a daily mail#
The recurring ask: a daily message showing not just the day's total but each shift's. A Measure Value segment carries one value — the current period's — so the daily message reaching backwards across the day's shifts needs the values to exist as measures the message can reference at its own trigger time.
The pattern: reference the shiftly measure several times with period offsets is not what segments offer — instead, create small calculated daily measures that reach back (Measure_<shiftly>[-2].Value, [-1], [0] at day-close resolve to the day's three shifts) and add each as its own segment. Three tiny measures, three segments, labelled "Morning / Afternoon / Night", and the daily mail carries the breakdown. The same trick serves "yesterday vs today" comparisons in a message.
When a message stops being delivered#
A definition that worked and went quiet is nearly always addressing: a recipient's address became invalid (a leaver, a renamed mailbox), and delivery fails per attempt. One diagnostic honesty note — the failure log does not always name the offending address or channel, so on a multi-recipient channel the practical isolation is to split recipients across test sends until the failing address is found. Keep channel membership tied to roles rather than named individuals and reviewed periodically (Building an Alarm Strategy), which prevents most of these.
Designing a message#
Say what happened, where, when, and how bad. "Boiler 1 pressure high, 1.62 MPa at 14:20, limit 1.50" is actionable. "Limit exceeded" is not.
Include the value and its limit. The recipient needs to know the magnitude of the breach to judge urgency.
Include a link or the dashboard. The next thing anyone does is look at the context. Provide it.
Keep it short for interrupt channels. SMS and chat want a sentence. Email can carry a report.
Name the measure as people know it. The message uses the measure's name, which is another reason names should be readable rather than coded.
Say what to do, if there is a standard response. A message that includes "check the relief valve" is worth several that just report a number.
Diagnosing#
| Symptom | Check |
|---|---|
| No messages at all | Message Engine deployed? Notification servers deployed? |
| Messages stuck at Compiled | Delivery — notification server credentials and network path |
| Messages Failed | The definition — a segment referencing something unavailable |
| Message content has blanks | A Measure Value segment whose measure had no value for that period |
| Summary arrives later than expected | Period Ended waits for values; a slow source or chain delays it |
| Alarm never fires | The limit, not the message — check its threshold and type |
| Alarm fires constantly | Limit set inside the normal operating range |
| Values in the message formatted oddly | Format string on the measure |
| Report segment empty | The report cannot render — check it in the browser first |