Skip to content
maintainx-reference-architecture logo

MaintainX Reference Architecture

maintainx-reference-architecture

Production-grade architecture patterns for MaintainX integrations.

SKILL.md

Full skill instructions

MaintainX Reference Architecture

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

PatternFailure ModeMitigation
Event-drivenPub/​Sub delivery failureDead letter queue, retry policy
Bi-directional syncConflict on same recordLast-write-wins or manual resolution
Analytics pipelineIncomplete data fetchRetry with backfill, validate counts
Multi-siteOne site API key expiredIndependent health checks per site

Resources

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'],
  });
}

More skills from jeremylongshore

openrouter-compliance-review logo
jeremylongshore/claude-code-plugins-plus-skills

openrouter-compliance-review

Review OpenRouter integration for regulatory compliance (SOC2, GDPR,

2.8K 0
View
maintainx-data-handling logo
jeremylongshore/claude-code-plugins-plus-skills

maintainx-data-handling

Data synchronization, ETL patterns, and data management for MaintainX.

2.8K 0
View
groq-core-workflow-a logo
jeremylongshore/claude-code-plugins-plus-skills

groq-core-workflow-a

Execute Groq primary workflow: chat completions with tool use and JSON

2.8K 0
View
validating-csrf-protection logo
jeremylongshore/claude-code-plugins-plus-skills

validating-csrf-protection

Validate CSRF protection implementations for security gaps. Use when

2.8K 0
View
api-contract logo
jeremylongshore/claude-code-plugins-plus-skills

api-contract

Configure this skill should be used when the user asks about "API contract",

2.8K 0
View
ideogram-incident-runbook logo
jeremylongshore/claude-code-plugins-plus-skills

ideogram-incident-runbook

Execute Ideogram incident response with triage, mitigation, and postmortem.

2.8K 0
View
gamma-sdk-patterns logo
jeremylongshore/claude-code-plugins-plus-skills

gamma-sdk-patterns

Reusable patterns for the Gamma REST API (no SDK exists).

2.8K 0
View
deepgram-sdk-patterns logo
jeremylongshore/claude-code-plugins-plus-skills

deepgram-sdk-patterns

Apply production-ready Deepgram SDK patterns for TypeScript and Python.

2.8K 0
View
openrouter-upgrade-migration logo
jeremylongshore/claude-code-plugins-plus-skills

openrouter-upgrade-migration

Migrate to OpenRouter from direct provider APIs or upgrade between SDK/model

2.8K 0
View
openrouter-common-errors logo
jeremylongshore/claude-code-plugins-plus-skills

openrouter-common-errors

Diagnose and fix common OpenRouter API errors. Use when encountering

2.8K 0
View
linear-cost-tuning logo
jeremylongshore/claude-code-plugins-plus-skills

linear-cost-tuning

Optimize Linear API usage, reduce unnecessary calls, and maximize

2.8K 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View