MaintainX Reference Architecture
SkillDev tools'Production-grade architecture patterns for MaintainX integrations.
Use MaintainX Reference Architecture in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add MaintainX Reference Architecture and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the MaintainX Reference Architecture skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by jeremylongshore/tons-of-skills-marketplace in skills/.curated/maintainx-reference-architecture/SKILL.md and read by Ahel’s review.
Overview
Production-grade architecture patterns for building scalable, maintainable integrations between MaintainX and enterprise systems (ERP, SCADA, data warehouses).
Prerequisites
- Understanding of distributed systems
- Cloud platform experience (GCP, AWS, or Azure)
- MaintainX API familiarity
Instructions
Step 1: Event-Driven Sync Architecture
The recommended architecture for most MaintainX integrations. Uses webhooks for real-time updates and scheduled jobs for reconciliation.
MaintainX API ──webhook──→ Cloud Run ──→ Pub/Sub ──→ Cloud Functions
│
├──→ BigQuery (analytics)
├──→ ERP System (SAP, Oracle)
└──→ Notification Service
// src/architecture/event-driven.ts
import express from 'express';
import { PubSub } from '@google-cloud/pubsub';
const app = express();
const pubsub = new PubSub();
const topic = pubsub.topic('maintainx-events');
// Webhook receiver publishes to Pub/Sub
app.post('/webhooks/maintainx', async (req, res) => {
const { event, data } = req.body;
await topic.publishMessage({
data: Buffer.from(JSON.stringify({ event, data })),
attributes: { event, resourceId: String(data.id) },
});
res.status(200).json({ status: 'queued' });
});
// Subscriber processes events asynchronously
const subscription = pubsub.subscription('maintainx-events-sub');
subscription.on('message', async (message) => {
const { event, data } = JSON.parse(message.data.toString());
switch (event) {
case 'workorder.completed':
await syncToERP(data);
await updateAnalytics(data);
break;
case 'workorder.created':
if (data.priority === 'HIGH') {
await sendUrgentNotification(data);
}
break;
}
message.ack();
});
Step 2: Bi-Directional Sync Gateway
For integrating MaintainX with ERP systems (SAP, Oracle) where changes flow both ways.
ERP (SAP/Oracle) ←──→ Sync Gateway ←──→ MaintainX API
│
Conflict Resolution
+ Audit Trail
+ Sync State DB
// src/architecture/sync-gateway.ts
interface SyncRecord {
externalId: string; // ERP system ID
maintainxId: number; // MaintainX ID
lastSyncAt: string;
syncDirection: 'inbound' | 'outbound' | 'bidirectional';
hash: string; // Content hash for change detection
}
class SyncGateway {
constructor(
private maintainx: MaintainXClient,
private erp: ERPClient,
private db: SyncStateDB,
) {}
// MaintainX → ERP
async syncToERP(workOrder: any) {
const existing = await this.db.findByMaintainxId(workOrder.id);
if (existing && this.hash(workOrder) === existing.hash) {
return; // No change, skip
}
const erpRecord = this.mapToERP(workOrder);
if (existing) {
await this.erp.update(existing.externalId, erpRecord);
} else {
const created = await this.erp.create(erpRecord);
await this.db.create({
externalId: created.id,
maintainxId: workOrder.id,
lastSyncAt: new Date().toISOString(),
syncDirection: 'outbound',
hash: this.hash(workOrder),
});
}
}
// ERP → MaintainX
async syncFromERP(erpRecord: any) {
const existing = await this.db.findByExternalId(erpRecord.id);
const woData = this.mapFromERP(erpRecord);
if (existing) {
await this.maintainx.updateWorkOrder(existing.maintainxId, woData);
} else {
const created = await this.maintainx.createWorkOrder(woData);
await this.db.create({
externalId: erpRecord.id,
maintainxId: created.id,
lastSyncAt: new Date().toISOString(),
syncDirection: 'inbound',
hash: this.hash(created),
});
}
}
private mapToERP(wo: any) {
return {
title: wo.title,
status: this.mapStatus(wo.status),
priority: wo.priority,
completedAt: wo.completedAt,
};
}
private mapFromERP(erp: any) {
return {
title: erp.description,
priority: erp.urgency === 'HIGH' ? 'HIGH' : 'MEDIUM',
};
}
private mapStatus(status: string) {
const map: Record<string, string> = {
OPEN: 'PLANNED',
IN_PROGRESS: 'ACTIVE',
COMPLETED: 'FINISHED',
CLOSED: 'ARCHIVED',
};
return map[status] || 'UNKNOWN';
}
private hash(obj: any): string {
return require('crypto').createHash('md5')
.update(JSON.stringify(obj)).digest('hex');
}
}
Step 3: Analytics Data Pipeline
MaintainX API ──scheduled──→ Cloud Functions ──→ BigQuery
│
Looker / Metabase
│
KPI Dashboards:
- MTTR (Mean Time to Repair)
- PM Compliance %
- Work Order Backlog
- Asset Downtime
// src/architecture/analytics-pipeline.ts
interface MaintenanceKPIs {
mttr: number; // Mean Time to Repair (hours)
pmCompliance: number; // Preventive Maintenance compliance %
backlog: number; // Open work orders count
completionRate: number; // Orders completed / orders created
}
async function calculateKPIs(client: MaintainXClient): Promise<MaintenanceKPIs> {
const completed = await paginate(
(cursor) => client.getWorkOrders({ status: 'COMPLETED', limit: 100, cursor }),
'workOrders',
);
const open = await paginate(
(cursor) => client.getWorkOrders({ status: 'OPEN', limit: 100, cursor }),
'workOrders',
);
// MTTR: Average time from OPEN to COMPLETED
const repairTimes = completed
.filter((wo: any) => wo.createdAt && wo.completedAt)
.map((wo: any) => {
const created = new Date(wo.createdAt).getTime();
const completed = new Date(wo.completedAt).getTime();
return (completed - created) / 3600000; // hours
});
const mttr = repairTimes.length > 0
? repairTimes.reduce((a: number, b: number) => a + b, 0) / repairTimes.length
: 0;
// PM Compliance
const pmOrders = completed.filter((wo: any) =>
wo.categories?.includes('PREVENTIVE'),
);
const allPM = [...pmOrders, ...open.filter((wo: any) =>
wo.categories?.includes('PREVENTIVE'),
)];
const pmCompliance = allPM.length > 0 ? (pmOrders.length / allPM.length) * 100 : 100;
return {
mttr: Math.round(mttr * 10) / 10,
pmCompliance: Math.round(pmCompliance),
backlog: open.length,
completionRate: completed.length / (completed.length + open.length) * 100,
};
}
Step 4: Multi-Site Architecture
Site A (Plant) Site B (Warehouse) Site C (Office)
└── Local Agent └── Local Agent └── Local Agent
│ │ │
└─────────── Central Hub (Cloud Run) ────────────────┘
│
MaintainX API
(Org-level access)
// Central hub routing requests by site
const siteConfigs = {
'plant-austin': { orgId: 'org-1', apiKey: process.env.MX_KEY_PLANT },
'warehouse-dallas': { orgId: 'org-2', apiKey: process.env.MX_KEY_WAREHOUSE },
'office-houston': { orgId: 'org-3', apiKey: process.env.MX_KEY_OFFICE },
};
function getClientForSite(siteId: string): MaintainXClient {
const config = siteConfigs[siteId as keyof typeof siteConfigs];
if (!config) throw new Error(`Unknown site: ${siteId}`);
return new MaintainXClient(config.apiKey, config.orgId);
}
Output
- Event-driven architecture with Pub/Sub for decoupled processing
- Bi-directional sync gateway with conflict resolution and audit trail
- Analytics pipeline calculating maintenance KPIs (MTTR, PM compliance)
- Multi-site architecture with per-site API key isolation
Error Handling
| Pattern | Failure Mode | Mitigation |
|---|---|---|
| Event-driven | Pub/Sub delivery failure | Dead letter queue, retry policy |
| Bi-directional sync | Conflict on same record | Last-write-wins or manual resolution |
| Analytics pipeline | Incomplete data fetch | Retry with backfill, validate counts |
| Multi-site | One site API key expired | Independent health checks per site |
Resources
- MaintainX API Reference
- Google Cloud Pub/Sub
- Event-Driven Architecture
Next Steps
For multi-environment setup, see maintainx-multi-env-setup.
Examples
SCADA integration (pulling sensor data into MaintainX work orders):
// Auto-create work order when equipment sensor exceeds threshold
async function handleSensorAlert(sensorId: string, value: number, threshold: number) {
const asset = await findAssetBySensorId(sensorId);
await client.createWorkOrder({
title: `Sensor Alert: ${asset.name} - ${sensorId} exceeded threshold`,
description: `Value: ${value} (threshold: ${threshold}). Auto-generated from SCADA.`,
priority: value > threshold * 1.5 ? 'HIGH' : 'MEDIUM',
assetId: asset.maintainxId,
categories: ['CORRECTIVE'],
});
}
Signals
- GitHub stars
- 3k
- Forks
- 415
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
maintainx-reference-architecture- Source
- github.com/jeremylongshore/tons-of-skills-marketplace
github.com/jeremylongshore/tons-of-skills-marketplace
Related picks
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScriptbigquery-ai-ml
Skill · kilo-org
The pick for BigQuerybigquery-public
Skill · clawbio
The pick for BigQuerycrypto-executor
Skill · leoyeai
The pick for Cryptocrypto-primitives
Skill · a5c-ai
The pick for Crypto