Back to blog

Object Structure Design Patterns for Maximo Integrations

Most integration failures in Maximo trace back to poorly designed object structures. Here's how to build them correctly from the start.

Maximo Best PracticesIntegrationObject StructuresAPI Design

If you’ve built more than a handful of Maximo integrations, you’ve seen this pattern: an object structure that seemed reasonable during development becomes a maintenance liability six months into production. Performance degrades. Schema changes break downstream systems. What should be a simple field addition requires regression testing across three external applications.

The problem isn’t the integration technology. It’s the object structure design.

The Two Failure Modes

Object structures in Maximo fail in predictable ways:

Over-flattening — cramming everything into a single object structure to “keep it simple”. This produces brittle integrations that expose unnecessary data, create tight coupling, and make versioning impossible.

Over-nesting — replicating the entire Maximo data model in hierarchical structures because “we might need it later”. This kills performance, complicates parsing, and creates maintenance overhead when unrelated schema changes ripple through the integration.

Both stem from the same mistake: designing the object structure around what Maximo has rather than what the integration needs.

Start with the Contract

Define the integration contract first. Not the object structure — the actual business transaction.

If you’re sending work orders to a mobile workforce system, the contract is “work assignment with location, asset, and task list”. It is not “work order with all possible relationships”.

The object structure should model the contract, not the database.

This sounds obvious, but most teams skip this step. They open the Object Structures application, find MXWODETAIL, clone it, and start removing fields. The result is a structure that still reflects Maximo’s internal data model rather than the external system’s needs.

Instead:

  1. Document what the consuming system actually requires
  2. Map those requirements to Maximo objects
  3. Build the minimum structure that satisfies the contract
  4. Version it explicitly from day one

Depth Strategy

Nesting in object structures has a performance cost. Each level adds query complexity and payload size.

Use this hierarchy:

Level 0 (Root) — the primary business object (WORKORDER, ASSET, PM, etc.)

Level 1 — direct relationships that define the transaction (WOACTIVITY, WPLABOR, LOCATIONS, etc.)

Level 2 — reference data required for context (PERSON for labour assignments, ASSETSPEC for technical attributes)

Level 3 and beyond — treat this as a code smell. If you need data three levels deep, you’re likely exposing implementation details rather than business concepts.

Example: If you need asset specification values in a work order integration, don’t traverse WORKORDER → ASSET → ASSETSPEC. Instead, evaluate whether those specifications should be denormalised into the work order itself (via automation script at creation time) or fetched separately through a dedicated asset query.

Exclude Everything by Default

Maximo’s object structure builder includes all fields by default. Reverse this.

Start with an empty structure. Add only the fields explicitly required by the integration contract. Every included field is a maintenance liability — it’s something that could change, something that needs documentation, something that consumers might start depending on.

This applies especially to system fields (CHANGEBY, CHANGEDATE, ROWSTAMP, etc.). If the consuming system doesn’t use them, exclude them.

The exception: primary keys and foreign keys required for relationship integrity. Include these even if the consumer doesn’t explicitly use them, because they’re necessary for processing.

Query vs. Publish Structures

Not all object structures serve the same purpose. Separate them by usage pattern:

Query structures — optimised for external systems requesting data. These should be shallow, focused, and performant. Example: ASSET_QUERY for mobile lookups.

Publish structures — optimised for outbound integration messages. These can be deeper because they’re pushed asynchronously. Example: WORKORDER_COMPLETE for notifying external systems of closure.

Sync structures — bi-directional updates where external systems write back to Maximo. These must be minimal and strictly validated. Example: WORKORDER_STATUS for workflow updates.

Don’t try to build one structure that serves all three patterns. The performance and security requirements are different.

Handling Extensions

Custom fields and extended objects are unavoidable. Build for them explicitly.

If your Maximo implementation uses extended attributes or custom tables, create dedicated child objects in the structure rather than mixing them with standard fields.

For example, if you’ve added custom fields to WORKORDER via attribute extension:

<WORKORDER>
  <standard fields>
  <WORKORDEREXT>
    <CUSTOMFIELD1/>
    <CUSTOMFIELD2/>
  </WORKORDEREXT>
</WORKORDER>

This isolates customisations from standard schema, making upgrades cleaner. When IBM changes the base WORKORDER object in a new release, your custom extensions remain separate.

Versioning from Day One

Object structures have no built-in versioning. Add it yourself.

Use a naming convention that includes version: WORKORDER_MOBILE_V1, ASSET_QUERY_V2, etc.

When requirements change, create a new version rather than modifying the existing structure. Run both in parallel during transition periods. Deprecate old versions explicitly with documented timelines.

This prevents the common scenario where a “small integration change” breaks three other systems that were quietly depending on the same object structure.

Testing Performance Early

Object structure performance problems don’t appear during development with test data. They appear in production with 500,000 work orders.

Before deploying a structure to production:

  1. Test with realistic data volumes
  2. Measure payload size for typical queries
  3. Check query execution plans for the underlying SQL
  4. Profile integration endpoint response times

If a single work order query returns a 200KB JSON payload, your structure is probably over-specified.

The Maintenance Test

Ask this question: if a developer unfamiliar with this integration needed to add one new field, how many places would they need to change?

The answer should be two: the object structure definition and the consuming system’s parser.

If the answer involves “and update the mapping logic, and modify the transformation script, and adjust the validation rules”, your structure is too complex.

What Good Looks Like

A well-designed object structure:

  • Models the business transaction, not the database schema
  • Includes only fields required by the contract
  • Nests no more than two levels deep for query operations
  • Isolates custom extensions from standard objects
  • Has an explicit version in its name
  • Produces payloads under 50KB for typical operations
  • Can be modified without cascading changes to unrelated systems

This isn’t theoretical. These patterns emerge from production Maximo implementations across utilities, transportation, manufacturing, and public sector organisations. The teams that follow them spend less time fighting integration bugs and more time delivering business value.

Start with the contract. Build the minimum structure. Version explicitly. Test with real data.