Almost every Maximo site eventually wants its work order, asset, and cost data inside Power BI. The reporting that ships with Maximo is fine for operational lists, but the moment a director asks for a portfolio view of backlog, PM compliance, and labour cost across sites, you need a proper semantic model. The question is never "can Power BI read Maximo" (it can), it is "how do I connect the two without setting fire to production." This guide compares the four routes that actually work in the field, gives each an architecture diagram, lists the core tables you will touch, and then walks the one pattern I recommend for most sites.
The four routes at a glance
Every Power BI to Maximo connection is a variation on one of four patterns. They are ordered here roughly from "lightest to stand up" to "heaviest, but strategic":
1. Direct read against a replica
Power BI imports from a read-only copy of the Maximo database. Fast to build, keeps load off production.
2. The REST / OSLC API
Power BI calls Maximo's own web service. Respects app-server security but is slow at volume.
3. MIF outbound to a staging DB
Maximo pushes records out through the Integration Framework into a reporting database you own.
4. MAS-native export to a lake
Maximo Application Suite streams data to a lake or warehouse; Power BI reads from there.
If you take one rule from this article, take this one: never point Power BI DirectQuery at the production Maximo database. I will come back to why, because it is the single most common and most damaging mistake I see. For now, let's look at each route properly.
Method 1: Direct read against a replica
The simplest reliable approach is to give Power BI a read-only replica of the Maximo database and import from it on a schedule. The replica can be a native database read replica (Oracle Data Guard, Db2 HADR standby opened read-only, SQL Server Always On readable secondary) or a nightly restored copy. Power BI connects with the standard Oracle, Db2, or SQL Server connector, runs its queries against the replica, and never touches the live instance.
The trade-offs:
- Setup effort: low to moderate. If a replica already exists for DR, you are mostly writing SQL views. If not, your DBA sets one up once.
- Refresh performance: excellent. Import mode means visuals hit Power BI's compressed cache, not the database, so dashboards are instant.
- Security model: a database login. Maximo's application security does not come with it, which is both the strength (simple) and the risk (you must rebuild row-level rules yourself).
- Risk to production: minimal, by design. All query load lands on the replica.
Method 2: The REST / OSLC API
Maximo exposes its data through the OSLC and REST APIs. Power BI can call these endpoints with the Web connector, authenticate as a Maximo user, and pull JSON back. Because the request goes through the application server, it honours everything Maximo enforces: site security, conditional data restrictions, and object structure field selection. For a small, tightly scoped extract this is genuinely elegant.
The trade-offs:
- Setup effort: moderate. You build an object structure, then wrestle Power BI M code to page through results and flatten nested JSON.
- Refresh performance: poor at volume. The API pages in batches through the app server, so pulling half a million work orders is painfully slow and adds real load to the tier your users run on.
- Security model: the best of the four. Requests inherit the calling user's Maximo permissions, including site restrictions.
- Risk to production: moderate. Heavy extracts compete with live users for the same application server threads.
When the API is the right call
Use OSLC when the dataset is small, near real-time, and security-sensitive: an open safety work order feed, a permit-to-work status board, an SLA breach alert. Do not use it as your bulk history extract. The API is a scalpel, not a shovel.
Method 3: MIF outbound to a staging database
The Maximo Integration Framework (MIF) is designed to push data out. You define a publish channel and an outbound object structure, and Maximo sends records, either event-driven on save or in scheduled batches, to an endpoint you control. Point that endpoint at a staging database, and you build your own clean reporting store that Power BI reads from. This is the classic enterprise pattern and the one large sites with a data team usually land on. IBM's Integration Framework documentation covers the channel and endpoint setup in detail.
The trade-offs:
- Setup effort: high. Channels, object structures, endpoints, error handling, and a staging schema all have to be built and maintained.
- Refresh performance: very good for Power BI. The heavy lifting is done by MIF ahead of time; Power BI reads a purpose-built, already-shaped store.
- Security model: you own the staging DB, so you design access from scratch. Maximo's site security does not travel through the channel.
- Risk to production: low to moderate. Event-driven publishing adds a small overhead to every transaction; keep bulk syncs on a schedule, off peak.
Method 4: MAS-native export to a lake
If you are on Maximo Application Suite (MAS) rather than Maximo 7.6, you get a fourth option that did not exist before. MAS Manage can stream operational data to a data lake or warehouse through its own data export and streaming features, landing records in object storage or a lakehouse. Power BI then reads from that lake, typically alongside data from other systems. This is less a Maximo reporting connection and more a feed into an enterprise analytics platform.
The trade-offs:
- Setup effort: highest, and it needs a lake platform and the skills to run it. Overkill if all you want is a maintenance dashboard.
- Refresh performance: excellent and scalable, because the lake is built for analytical query volume.
- Security model: governed at the lake and Power BI layer. Again, nothing of Maximo's own security survives the trip.
- Risk to production: low. Export runs on MAS infrastructure separate from the interactive workload.
The four methods compared
| Factor | 1. Replica | 2. REST / OSLC | 3. MIF staging | 4. MAS lake |
|---|---|---|---|---|
| Setup effort | Low to moderate | Moderate | High | Highest |
| Refresh performance | Excellent | Poor at volume | Very good | Excellent |
| Security model | DB login (rebuild RLS) | Maximo user (best) | You own it | Lake / BI governed |
| Risk to production | Minimal | Moderate | Low to moderate | Low |
| Best for | Most FM / EAM sites | Small live feeds | Large data teams | MAS + enterprise analytics |
There is no single winner; the right choice depends on your volume, your security appetite, and whether you have a data team. But for the typical facility or asset site that wants trustworthy dashboards without a lake programme, method one wins on effort versus payoff. The rest of this guide is about doing it well.
One aside worth making: none of these patterns is unique to Maximo. When I connect Power BI to an ERP, the same options appear, and I have written up the equivalent decision for finance data in connecting Power BI to Business Central. The instincts transfer directly.
The Maximo tables you will need
Whichever route you take, you end up modelling the same handful of core objects. Maximo has thousands of tables, but a maintenance and cost analytics model rests on these eight. The join keys below are the ones that matter, and every one of them is scoped by SITEID (and often ORGID), which becomes important in the next section.
| Table / view | What it holds | Key columns / join keys |
|---|---|---|
| WORKORDER | Work orders, tasks, PMs generated as WOs | WONUM (pk) · ASSETNUM → ASSET · LOCATION → LOCATIONS · SITEID, ORGID |
| ASSET | Asset register and hierarchy | ASSETNUM + SITEID (pk) · PARENT → ASSET · LOCATION → LOCATIONS |
| LOCATIONS | Functional locations and hierarchy | LOCATION + SITEID (pk) · joined from WORKORDER and ASSET |
| LABTRANS | Labour transactions (hours and cost) | REFWO → WORKORDER.WONUM · LABORCODE · SITEID |
| MATUSETRANS | Material usage against work | REFWO → WORKORDER.WONUM · ITEMNUM → INVENTORY · SITEID |
| FAILUREREPORT | Failure, problem, cause, remedy codes | WONUM → WORKORDER · FAILURECODE hierarchy · SITEID |
| PM | Preventive maintenance definitions | PMNUM (pk) · ASSETNUM → ASSET · LOCATION → LOCATIONS · SITEID |
| INVENTORY | Storeroom stock and balances | ITEMNUM + ITEMSETID + SITEID (pk) · joined from MATUSETRANS |
Watch the schema: Maximo 7.6 vs MAS Manage
The good news is that the base table names above are stable across Maximo 7.6 and MAS Manage: WORKORDER, ASSET, and the rest keep their names. What changes underneath is the platform and the extras. MAS Manage often runs on a different database engine (Db2 Warehouse or PostgreSQL rather than the Oracle or Db2 you had on 7.6), the schema owner may differ from maximo, and MAS adds attributes and object structures that 7.6 never had. Do not assume your 7.6 SQL runs unchanged against MAS; the column list on WORKORDER in particular grows between versions. Always confirm names and data types against the live target before you build views.
Rebuilding row-level security
Here is the trap that catches people. In Maximo, a user in the Dubai site sees only Dubai work orders because the application server filters every query by the user's site authorisations. That security lives in the app tier. The moment you read from a replica, a staging database, or a lake, you have gone around the application server, and none of that filtering comes with you. A database login sees every row in every site.
So if your Power BI report must respect who-sees-what, you have to rebuild it in the model. In practice that means implementing Power BI row-level security (RLS) roles that filter on SITEID and, for multi-organisation estates, ORGID, then mapping users or security groups to the sites they are allowed to see. It is not hard, but it is a deliberate design step that has to be planned in from the start, not bolted on after a manager notices they can see another region's costs.
Caution: do not skip the RLS design
The most common data-governance incident I see on Maximo reporting is not a hack, it is a well-meaning dashboard that quietly exposes every site's labour cost to everyone with a Power BI licence, because the builder assumed Maximo's site security would carry over. It does not. Treat SITEID and ORGID filtering as a mandatory part of the model, not an optional extra. This is exactly the kind of decision covered in configuration versus customisation: security belongs in configured, repeatable rules, not in ad hoc report filters.
Step-by-step: replica plus scheduled import
For most sites, the pattern that gives the best result for the least risk is method one done carefully: a read replica, clean SQL views, an Import-mode model, RLS, and a scheduled refresh. Here is how I build it. (If you are new to Maximo itself, my introduction to IBM Maximo sets the context for the objects referenced below.)
- Stand up a read replica. Have your DBA provision a read-only standby (Data Guard, HADR readable standby, Always On secondary) or a nightly restored copy. This is the single most important step, because it is what keeps every query below off production.
- Create reporting views on the replica. Build a small set of clean views (
vw_workorder,vw_labour_cost,vw_pm_compliance) that pre-join the core tables, filter to active records, and expose only the columns the model needs. Views give you a stable contract even if the schema shifts under a version upgrade. - Connect Power BI in Import mode, not DirectQuery. Use the native Oracle, Db2, or SQL Server connector against the replica. Import mode pulls the data into Power BI's compressed engine so visuals are fast and the database is queried only at refresh time.
- Model the star schema. Make WORKORDER, LABTRANS, and MATUSETRANS your fact tables; ASSET, LOCATIONS, PM, and a date table your dimensions. Join on the keys from the table above. A clean star is what makes the whole thing performant and easy to extend.
- Add row-level security. Define RLS roles filtering on
SITEIDandORGID, and map your Power BI security groups to them. Test by viewing the report as a restricted user before you publish. This is not optional, as the section above explains. - Schedule the refresh. Set the dataset to refresh on a schedule that matches how fresh the data needs to be, usually nightly, timed after the replica has caught up and off the operational peak. For most maintenance reporting, overnight is plenty.
- Monitor refresh duration and view performance. Watch how long refresh takes as history grows, and add incremental refresh once volumes justify it so you reload only recent partitions rather than the full history each night.
That is the whole pattern. It is unglamorous, it is robust, and it scales from a single site to a large multi-org estate without changing shape. Microsoft's Power BI documentation covers the Import mode, RLS, and incremental refresh mechanics in depth if you want the button-level detail.
Conclusion
Four routes, one recurring lesson: keep the analytical load off your live Maximo and rebuild the security you left behind when you went around the application server. The replica-plus-scheduled-import pattern is where most sites should start, the REST API earns its place for small live feeds, and MIF or a MAS lake come into play when a data team and enterprise scale justify them. Whatever you choose, do not point DirectQuery at production. A single unfiltered work-order visual will happily table-scan the live database and stall the technicians' mobile sync mid-shift, and no dashboard is worth that.
Independence note: I am not affiliated with, sponsored by, or reselling for IBM or Microsoft. The methods and recommendations here reflect my own field experience across Maximo and Power BI implementations, not any vendor's guidance. Verify version-specific details against your own environment and the current official documentation before you build.
Written by Muhammad Abbas
CMMS / CAFM Manager & Enterprise Integration Specialist · 22+ years across ERP, EAM, CAFM and enterprise integration.
Work with me