How it is built
Architecture overview
Enterprise asset management (EAM) keeps physical assets (pumps, vehicles, buildings, rail track, pipelines) working over their whole life. It grew out of the computerised maintenance management system (CMMS) and adds life-cycle, warranty, mobile and portal functions on top of maintenance planning (source: Wikipedia, Enterprise asset management). A commercial suite such as IBM Maximo describes the same scope as asset and work management, monitoring with sensor and meter data, prediction, and investment planning (source: IBM, Maximo product page).
At the centre is one small loop: an asset (a node in a hierarchy) has a plan (time- or meter-based rules), the plan produces work orders, the work orders consume labour and spare parts, and the history of finished work feeds back into reliability analysis that changes the plan. Everything else is an input to that loop (sensor readings, failures reported by people) or an output of it (cost, compliance records). The design problems are therefore data-shaped rather than algorithmic: a deep, changing asset tree; generation of recurring work from rules; a work-order state machine with approvals; intermittent, hard-to-forecast demand for spare parts; field crews without network; and an audit trail that stands up to a regulator.
Parts:
- Asset registry — the tree of locations, systems, equipment and components, with a register of every item and its location —
closure-table(no page yet),linear-referencing(no page yet), Optimistic concurrency control, Geospatial cell index (geohash, S2, H3) - Preventive planning — turns "every 3 months" or "every 5,000 operating hours" into dated work — Recurrence rule expansion,
calendar-date-arithmetic(no page yet),business-day-calendars(no page yet), Durable job queue - Work management — the work order from request to close, with approval, scheduling and execution — Hierarchical state machine, Durable workflow execution,
event-condition-action-rules(no page yet), Job-shop scheduling - Condition monitoring — sensor and PLC data that opens work when a condition holds —
opc-ua(no page yet),mqtt-protocol(no page yet), Windowed stream aggregation, Control charts (Shewhart, CUSUM, EWMA), Time-series anomaly detection - Reliability analytics — failure statistics, remaining life, and fault logic —
weibull-reliability-analysis(no page yet),remaining-useful-life-estimation(no page yet), Fault tree analysis - Spares and inventory — stock of parts, safety levels, reservations to work orders, scanning —
inventory-policies-safety-stock(no page yet),croston-method(no page yet),inventory-reservation(no page yet),barcode-symbologies(no page yet) - Mobile client — crews work from a handheld in basements and plants without signal — Offline mutation queue, Incremental sync cursors
- Audit and access — who changed what, who may do what — Tamper-evident audit log, Authorization models (RBAC, ABAC, ReBAC)
sensors / PLCs ─OPC UA, MQTT─► gateway ─► rule engine ──────────────┐ (condition met → request)
▲ ▼
PM plans (time / meter) ─► generator job ───►│ work request ─► work order (state machine, approvals)
(recurrence rules, │ │ │ │
calendars) asset registry (tree) ◄── history ◄──────┘ │ │
▲ │ ▼ ▼
reliability analysis ┘ parts reservation crew schedule
(Weibull, RUL, fault tree) (stock, safety level) (skills, calendars)
▲ │ │
└──────────── actuals (time, parts, failure codes) ◄─┘
▲
mobile app (offline queue, barcode scan) ┘
every write ─► audit log (hash chain)
How the parts fit together
Asset registry
Assets form a tree (site, building, line, machine, component), and the same piece of equipment often also belongs to a second view (a process system, a cost centre). Work, cost and failures must roll up the tree, so queries such as "all open work under this line, at any depth" are the common ones. A closure table (closure-table, no page yet) stores every ancestor-descendant pair, which makes subtree queries a single join; the price is that moving a subtree rewrites its rows, acceptable because assets move rarely. The alternative, recursive queries on a parent column, is simpler but slower on deep trees. A tree rebuilt at every read does not scale to hundreds of thousands of assets.
Linear assets (a rail line, a pipeline, a road) are not points. Their locations are given as a distance along the route, and a defect or a repair is a point or a stretch on it; when the route is realigned, the stored measures are recalculated, which is a known maintenance burden of the method (source: Wikipedia, Linear referencing, block linear-referencing, no page yet). Point assets such as a lift or a transformer are geo-referenced and placed on a map with a Geospatial cell index (geohash, S2, H3). Edits to one asset by several users use Optimistic concurrency control: a version number on the row, so a stale save fails visibly instead of silently overwriting.
Preventive planning
A preventive-maintenance (PM) plan states a frequency (calendar, runtime or both), a lead time and a work-order template. The generator expands the rule into dates (Recurrence rule expansion, which handles "last Friday of the month" and exceptions), uses calendar rules (calendar-date-arithmetic, business-day-calendars, both no page yet) to move a due date off a holiday or a shutdown, and creates the next work order from the template. For meter-based plans the trigger is a counter reading rather than a date: the plan keeps the reading at last completion and the interval, and a new reading that crosses the threshold generates the order.
The generator is a periodic job that must be idempotent: re-running it after a crash must not create the same order twice. A Durable job queue with a natural key (plan id plus due date) gives that. A common design choice is to generate orders a fixed horizon ahead (for example the next two months) rather than all at once, so a plan change only needs to revisit orders not yet released.
Work management
A work order has a life: requested, approved, planned, scheduled, in progress, completed, closed or cancelled. Rules differ by state (a cancelled order cannot take new actuals; a closed one is frozen), and a parent order can have child orders and tasks with their own states, so a flat status column is not enough. A Hierarchical state machine encodes this, with nested states for the shared behaviour (everything "open" accepts comments) and transitions guarded by role and by content (an order cannot close without a failure code). Long approval chains, waits for parts, and retries run on Durable workflow execution, so a deploy or a crash does not lose an order half-way through approval.
Event-condition-action rules (event-condition-action-rules, no page yet) add the reactive glue: "when a reading exceeds X and no open order exists for this asset, create a corrective request". They are kept as data so planners can edit them without a release. Scheduling the crew is a job-shop style problem with skills, calendars and priorities (Job-shop scheduling); most products ship a manual board with checks rather than a solver, and a solver is added where shutdown windows are tight.
Condition monitoring
Sensors reach the system through industrial protocols. OPC UA (opc-ua, no page yet) is the machine-vendor-neutral standard for reading structured values from controllers, and MQTT (mqtt-protocol, no page yet), a publish-subscribe protocol, is the usual link for lightweight sensor feeds (source: OASIS MQTT 5.0 specification; OPC Foundation reference). A gateway at the plant reads or subscribes, adds an asset id and timestamp, and forwards.
The raw stream is far too large to keep as is: Windowed stream aggregation reduces it to per-asset windows (mean, max, count over threshold). Thresholds on a window are the simplest rule; a Control charts (Shewhart, CUSUM, EWMA) approach catches drift that a fixed threshold misses, and Time-series anomaly detection covers the case where "normal" depends on load. The output is a request through the rule engine, never a work order written directly, so the same approval and de-duplication rules apply.
Reliability analytics
Completed work orders with failure codes are the data. The Weibull distribution (weibull-reliability-analysis, no page yet) is the standard failure-time model; its shape parameter tells whether the failure rate falls, stays constant or rises with age, and the constant case is the exponential model (source: NIST/SEMATECH e-Handbook of Statistical Methods, Weibull page). Fitted per component class, it tells the planner whether time-based replacement helps at all: when the rate is constant, replacing early does not reduce failures. Weibull's original paper is the classic reference (Weibull 1951).
Remaining-useful-life estimation (remaining-useful-life-estimation, no page yet) uses a monitored degradation signal to predict when a threshold will be crossed; Si et al. 2011 review the statistical data-driven approaches. Fault tree analysis works top-down for safety-critical systems: it combines component failure probabilities into the probability of a system-level event and identifies single points of failure. These analyses feed reliability-centred maintenance, a method that asks, per failure mode, what task (if any) is worth doing (source: Wikipedia, Reliability-centered maintenance, which cites SAE JA1011 as the minimum criteria for an RCM process). Their output is a change in a plan's interval or task list, which closes the loop.
Spares and inventory
Parts are different from ordinary retail stock: most are used rarely and irregularly, and a missing one can stop a plant. Demand with many zero periods defeats ordinary smoothing; Croston's method (croston-method, no page yet) forecasts the demand size and the interval between demands separately (Croston 1972), and Syntetos and Boylan showed the original estimator is biased and proposed a correction. The forecast feeds a reorder point and safety stock (inventory-policies-safety-stock, no page yet; see also Wikipedia, Reorder point).
Planned work reserves its parts in advance so a second order cannot claim the same stock (inventory-reservation, no page yet); the reservation is released if the order is cancelled. A barcode or QR scan identifies the part or the asset at the point of use (barcode-symbologies, no page yet), which cuts keying errors in the field. For the general time-series side see Time-series forecasting (baselines, model families, backtests).
Mobile client and audit
A technician works in a plant room with no coverage. Each action (start work, add time, scan a part, close the order) is recorded locally and queued with an id, then delivered exactly once when the network returns (Offline mutation queue), with changes flowing back down by cursor (Incremental sync cursors). Conflicts are rare because one order has one assignee, and versions from the registry catch the rest.
Maintenance records are evidence: a regulator may ask who inspected a lifting device and when. A Tamper-evident audit log chains every write with a hash, so edits or deletions afterwards are detectable. Access follows roles and plant scope (Authorization models (RBAC, ABAC, ReBAC)): a planner sees their site, a contractor sees only assigned orders.
Data and control flow
A preventive order, end to end:
- The nightly generator reads active PM plans, expands recurrence rules for the horizon and adjusts for calendars.
- For each due date it enqueues a job keyed by plan id and date; the job creates a draft order from the template and attaches the asset.
- The order enters the state machine; approval runs as a workflow with timers and reminders.
- On approval the planner assigns a crew and slot; parts are reserved.
- The technician opens the order on the handheld, scans the asset, logs time and parts, enters a failure code if one was found, and closes it; the app queues these offline.
- The server applies the mutations, releases or consumes the reservation, writes history to the asset, and appends the audit entries.
- Completion starts the clock for the next occurrence (for plans scheduled "from completion").
A condition-triggered request:
- A sensor value arrives through the gateway and is aggregated into a window.
- The rule engine evaluates the rule: threshold or control-chart signal, and no open order for this asset.
- It creates a request with the evidence (window, values) attached; a planner approves it into a work order.
- After the work, the failure code and readings go to reliability analytics.
Scaling
- Asset tree size and depth: with hundreds of thousands of assets, subtree reads dominate. Levers: closure table, cached rollups per node, and loading the tree lazily in the client.
- Sensor volume: tens of thousands of tags at one-second rates. Levers: aggregate at the gateway, store only windows and events, and keep raw data in a time-series store with short retention.
- Plan expansion: many plans times a long horizon. Lever: generate only the near horizon and re-run daily.
- Mobile sync: large downloads on weak links. Levers: scope the downloaded data to the crew's sites and assigned orders, sync by cursor, compress.
- Multi-site tenancy: sites with different calendars and languages. Lever: partition by site, with the tree as the shared parent.
Failure modes
| Failure | Symptom | Cause | Fix |
|---|---|---|---|
| Duplicate preventive orders | the same inspection appears twice | generator re-run without idempotency | job key of plan and date; unique constraint |
| Orders never generated | the maintenance backlog looks empty | plan expansion failed silently (invalid rule, time zone) | alert on a plan with no future order; test rules at save |
| Wrong due date at month end or holidays | order lands on a closed day | calendar arithmetic ignores working days or time zones | explicit calendar rules; store dates, not instants, for calendar-based plans |
| Meter plan never fires | a machine runs far past its interval | meter readings not entered or reset | alert on stale meters; validate monotonic readings |
| Alarm storm | hundreds of auto requests from one fault | rules have no de-duplication per asset | one open request per asset and rule; hold-off window |
| Stale asset save | a later edit silently overwrites an earlier one | no version check | optimistic concurrency with a version field |
| Double-booked part | two orders reserve the last item | reservation without a transactional check | reserve inside a transaction against available stock |
| Offline conflict | the technician's close is rejected after sync | order was cancelled or reassigned meanwhile | show the conflict, keep the local record, let the planner decide |
| Spare-part stock-out | an order waits for a part nobody stocked | smoothing on intermittent demand under-forecasts | intermittent-demand method; criticality-based minimum stock |
| Altered history | an auditor cannot trust past records | rows editable by admins without trace | hash-chained audit log; correction as a new entry |
Real implementations
Large suites are proprietary; the open projects below cover the core loop (assets, work orders, preventive plans) and the protocol layers.
| name | what it is | repo | licence | notes |
|---|---|---|---|---|
| IBM Maximo | commercial EAM suite: asset and work management, monitoring, prediction | — (closed source) | — | scope per IBM product page |
| Atlas CMMS | self-hosted CMMS: work orders, assets, preventive maintenance, mobile apps | Grashjs/cmms | AGPL-3.0 | web and mobile, Docker deployment |
| ERPNext | open ERP with an Asset module (register, depreciation, maintenance, movement) | frappe/erpnext | GPL-3.0 | asset docs: docs.frappe.io |
| openMAINT | open-source CMMS built on the CMDBuild configuration platform, with GIS and BIM support | openmaint.org | see site | maintained by PAT srl; source link not given on the home page |
| open62541 | OPC UA implementation in C for clients and servers | open62541/open62541 | MPL-2.0 | the plant-side protocol layer |
| Eclipse Milo | OPC UA implementation in Java | eclipse-milo/milo | EPL-2.0 | server and client SDK |
| NanoMQ | lightweight MQTT broker for the edge | nanomq/nanomq | MIT | gateway-side broker |
| Eclipse Ditto | digital-twin framework: a model of each device and its state | eclipse-ditto/ditto | EPL-2.0 | can hold the live state next to the asset record |
The alternative: a pure CMMS keeps only the work-order loop (equipment list, PM schedule, parts) and leaves finance, life-cycle and condition monitoring to other systems. It is quicker to introduce for one plant, but the asset record is split across tools; full EAM pays back when one asset tree has to serve operations, finance and compliance together.
Sources
- Wikipedia, Enterprise asset management (scope; origin in CMMS). page
- IBM, Maximo product page (suite scope). page
- Wikipedia, Linear referencing (measures along a route; maintenance burden). page
- Wikipedia, Reliability-centered maintenance (RCM questions, task types, SAE JA1011). page
- NIST/SEMATECH, e-Handbook of Statistical Methods, Weibull distribution. page
- W. Weibull, A Statistical Distribution Function of Wide Applicability, Journal of Applied Mechanics, 1951. DOI (publisher returns 403 to scripts; confirmed via Crossref)
- J. D. Croston, Forecasting and Stock Control for Intermittent Demands, Journal of the Operational Research Society, 1972. DOI (same note)
- A. A. Syntetos and J. E. Boylan, On the bias of intermittent demand estimates, International Journal of Production Economics, 2001. DOI
- X.-S. Si, W. Wang, C.-H. Hu and D.-H. Zhou, Remaining useful life estimation: a review on the statistical data driven approaches, European Journal of Operational Research, 2011. DOI
- Wikipedia, Reorder point. page
- OASIS, MQTT Version 5.0. spec
- OPC Foundation, OPC UA reference. reference
- ERPNext Asset documentation. docs
- openMAINT. site
- Repositories in the table above (licences from the GitHub API or the project's README).