Subscription is the efficient way to collect from a building: the device tells you when something changes instead of you asking repeatedly. The cost of that efficiency is state. Somebody, somewhere, is holding a list of who wants to be told what, and that list is fragile in ways polling is not. The characteristic failure is silence that looks like stability.
The message up front: treat subscriptions as soft state that must be continuously re-established rather than as configuration that is set once. Renew well before expiry, re-subscribe unconditionally after any restart at either end, reconcile what you believe you are subscribed to against what the devices think, and monitor for silence per point rather than monitoring the link. A subscription-based integration without an active reconciliation loop will degrade, quietly, and the first symptom will be a gap in data nobody noticed for weeks.
1. What a subscription actually is
Your collector asks a device to notify it when a specified point changes by more than a given increment. The device records that request, along with who asked and how long the request is valid for, and begins sending notifications. When the validity period elapses, the device forgets, and the notifications stop.
Three consequences follow, and all of the trouble comes from them:
- The state lives in the device, not in you. Your configuration says you want the data; the device's subscription list determines whether you get it. These two can disagree, and only the second is authoritative.
- It expires by design. That is a safety feature: it stops devices maintaining subscriptions forever for clients that have gone away. It also means renewal is mandatory rather than optional.
- Devices have finite capacity. A controller supports a limited number of concurrent subscriptions, and once that limit is reached further requests fail, often without anything useful being reported upstream.
The object model underneath this is covered in BACnet objects, device instances and addressing, and the choice between subscription and the alternatives in BACnet data logging.
2. The ways it lapses
| Event | What happens to the subscription | What you see |
|---|---|---|
| Gateway or collector restart | The device may still hold it, but your side has lost track and may not re-subscribe | Either duplicate subscriptions or none. Both are quiet |
| Controller restart | The device forgets everything. Your side believes it is subscribed | Silence from that device, indefinitely |
| Renewal missed | Expires normally | Silence from that point, at a time unrelated to any visible event |
| Network interruption during renewal | Renewal lost, subscription expires shortly after | Silence beginning minutes after a blip that looked recovered |
| Device subscription limit reached | New requests rejected | Some points work and others never do, often the ones added last |
| Point reconfigured or controller replaced | The object no longer exists, so the subscription cannot be re-established | Permanent silence, with the configuration still looking correct |
Every row produces the same symptom: no data and no error. That is what makes this different from a connection failure, which at least announces itself.
Monitor silence per point, not connectivity
A lapsed subscription is invisible to every connectivity check you have: the device answers, the link is up, the gateway is running. The only thing that detects it is noticing that a specific point has not reported for longer than it plausibly should have. That requires an expected-interval figure per subscribed point, which is a judgement rather than a measurement for change-driven data, but a generous one still works: a point that normally changes several times a day and has said nothing for a week has a problem. This is the same staleness mechanism described in the connectivity loss playbook, and subscriptions are the main reason it cannot be skipped.
3. Renewal discipline
- Renew at a fraction of the lifetime, not near the end. Renewing with substantial margin means a single missed renewal attempt does not cause a lapse, because the next attempt still lands inside the window.
- Treat a failed renewal as an event, not a retry. Log it, count it, and alarm if it repeats for the same device. A device that consistently rejects renewals is telling you something, usually that it is at its limit.
- Stagger renewals. Subscriptions established together expire together, so renewals cluster into a burst that can itself fail on a loaded trunk, taking out a whole group at once.
- Do not rely on unlimited-lifetime subscriptions even where a device offers them. They survive nothing: a controller restart clears them like any other, and they remove the regular renewal that would otherwise have detected the loss.
- Record the lifetime in use per device type, because it varies and because the renewal interval depends on it.
4. Recovery after a restart
Restarts are routine, and the behaviour on restart is what separates an integration that recovers from one that silently degrades.
- On collector startup, re-subscribe unconditionally to everything in the configuration. Do not try to work out what might still be active. Re-subscribing to something already subscribed is harmless on most devices; assuming a subscription survived is not.
- Detect device restarts and re-subscribe to that device. Devices advertise themselves on startup, and a collector that watches for this recovers within moments instead of at the next reconciliation.
- Read current values immediately after re-subscribing. A subscription only reports changes, so a point that changed while you were away and is now stable will never notify. Without a read, your value stays wrong until the next change, which could be days.
- Mark the gap. The period between losing the subscription and recovering it is a known blind window and should be flagged in the data rather than appearing as a stable value, which is the quality-flag approach in BACnet data quality flags.
- Persist the subscription inventory so a restarted collector knows what it should be subscribed to, rather than rebuilding it from a configuration file that may have drifted.
That third point is the one most often missed, and it produces a particularly confusing symptom: a value that is wrong but not stale, because it is being faithfully reported as unchanged since a change nobody saw.
5. Reconciliation
Renewal keeps subscriptions alive; reconciliation finds the ones that are not.
- Periodically compare intended against actual. For every point you believe you are subscribed to, confirm the subscription exists on the device where the device allows that to be queried. Where it does not, fall back to the silence check.
- Report the difference as a number, trended. Intended subscriptions, confirmed subscriptions, and the gap. A growing gap is the early warning.
- Re-establish automatically, then alarm on repeats. One lapse recovered silently is fine. The same point lapsing repeatedly is a device or capacity problem that needs a human.
- Include subscription health in the integration's own heartbeat, so that a collector running normally but holding no subscriptions is visibly abnormal.
6. Device limits, and designing within them
Controllers support a bounded number of concurrent subscriptions, and the limit is often lower than people expect on smaller terminal controllers. Exceeding it does not usually produce a clear error upstream; the request simply fails and the point never reports.
- Get the limit per device type from the manufacturer documentation or the protocol implementation conformance statement, and record it alongside the device in the point register.
- Count intended subscriptions per device against that limit before configuring, not after.
- Remember other clients. The head end may hold subscriptions of its own on the same devices, consuming the same budget, and your integration is not the only consumer.
- Prioritise deliberately where the limit binds: subscribe to the points where change matters, and poll the rest on a slow cycle per BACnet polling schedules.
- Leave headroom, because the next project will want to subscribe to something too.
7. Proving it works
None of the above can be assumed. Three tests, each taking minutes, during commissioning:
- Restart the collector and confirm every subscription re-establishes and current values are read, with the gap flagged.
- Restart one controller and confirm its subscriptions are detected as lost and re-established without manual intervention.
- Block renewals to one device for longer than the lifetime and confirm the silence is detected and reported rather than going unnoticed.
The third is the one that finds the gap in most implementations, and it belongs in the wider set in the BACnet integration acceptance test checklist.
Limits on this article
No lifetimes, renewal intervals, increment values or subscription counts are given, because they are device and platform properties that vary widely and are documented per product. Support for subscriptions is itself inconsistent: some devices implement them partially, some not at all, and the protocol implementation conformance statement is the authority on what a given device will actually do. This article is written from the integration and data side, which is my own domain; configuring and troubleshooting the controllers themselves is work for whoever maintains the controls.
The idea to walk away with
A subscription is state held by somebody else, with an expiry, and therefore something to be continuously maintained rather than configured. Build the integration on that assumption: renew early, re-subscribe unconditionally after any restart, read current values on recovery, reconcile what you intend against what exists, and detect silence per point.
The alternative is an integration that works perfectly at handover and is missing a slowly growing set of points a year later, with nothing anywhere reporting a fault.
Final thoughts
If you run a subscription-based integration and have never checked, the diagnostic is one query: for every subscribed point, when did it last report. Sort ascending.
The points at the top of that list have usually been silent far longer than anyone would have guessed, and several of them will turn out to belong to controllers that were restarted or replaced months ago. That list is both the problem and the business case for building the reconciliation loop.
Disclosure
Alongside advisory work I also build a CMMS and CAFM platform, so I have a commercial interest in this category. Nothing above is a recommendation for it, and no vendor named here has paid for inclusion or had any editorial input. Weigh the analysis accordingly.
Points that stopped reporting?
Independent review of subscription lifecycle handling: renewal margin, restart recovery, reconciliation, device limits and the silence detection that catches a lapse before it becomes a data gap. 22+ years across CMMS, CAFM, EAM and ERP implementations.
Book a conversationRelated reading: BACnet data logging, BACnet polling schedules, Connectivity loss playbook, BACnet data quality flags, BACnet acceptance test checklist, BACnet objects and addressing.
Muhammad Abbas
CMMS / CAFM Manager & Independent Advisor · 22+ years across enterprise CMMS, EAM, CAFM and ERP implementations in utilities, oil and gas, manufacturing, government and facility operations.
Work with me