maintainx-reference-architecture
Production-grade architecture patterns for MaintainX integrations. Use when designing system architecture, planning integrations, or building enterprise-scale MaintainX solutions. Trigger with phrases like "maintainx architecture", "maintainx design", "maintainx system design", "maintainx enterprise", "maintainx patterns". allowed-tools: Read, Write, Edit version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>
Allowed Tools
No tools specified
Provided by Plugin
maintainx-pack
Claude Code skill pack for MaintainX CMMS (24 skills)
Installation
This skill is included in the maintainx-pack plugin:
/plugin install maintainx-pack@claude-code-plugins-plus
Click to copy
Instructions
# MaintainX Reference Architecture
## Overview
Production-grade architecture patterns for building scalable, maintainable MaintainX integrations.
## Prerequisites
- Understanding of distributed systems
- Cloud platform experience
- MaintainX API familiarity
## Architecture Patterns
### Pattern 1: Event-Driven Integration
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MaintainX Platform β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Work Orders β β Assets β β Locations β β
β ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ β
β β β β β
β βββββββββββββββββββΌββββββββββββββββββ β
β β β
β ββββββββΌβββββββ β
β β Webhooks β β
β ββββββββ¬βββββββ β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your Integration Layer β
β β
β ββββββββββββββββββ ββββββββββββββββββ ββββββββββββββββββ β
β β Webhook HandlerβββββΆβ Event Queue βββββΆβ Event Processorβ β
β β (Express) β β (Redis/SQS) β β (Workers) β β
β ββββββββββββββββββ ββββββββββββββββββ βββββββββ¬βββββββββ β
β β β
β ββββββββββββββββββ ββββββββββββββββββ ββββββββΌβββββββββ β
β β API Gateway βββββΆβ MaintainX ClientβββββΆβ Data Store β β
β β (REST/GraphQL) β (Cached) β β (PostgreSQL) β β
β ββββββββββββββββββ ββββββββββββββββββ βββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β External Systems β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
β β ERP β β SCADA β β BI/Reportsβ β Slack β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
### Pattern 2: Sync Gateway Architecture
```typescript
// src/architecture/sync-gateway.ts
interface SyncGatewayConfig {
pollInterval: number;
batchSize: number;
retryPolicy: RetryPolicy;
}
class MaintainXSyncGateway {
private client: MaintainXClient;
private cache: CacheManager;
private eventEmitter: EventEmitter;
private syncState: Map;
constructor(config: SyncGatewayConfig) {
this.client = new CachedMaintainXClient(new MaintainXClient());
this.cache = new CacheManager(process.env.REDIS_URL!);
this.eventEmitter = new EventEmitter();
this.syncState = new Map();
}
// Bi-directional sync
async sync(): Promise {
const result: SyncResult = {
inbound: { created: 0, updated: 0, deleted: 0 },
outbound: { created: 0, updated: 0, deleted: 0 },
};
// Inbound: MaintainX -> Local
await this.syncInbound(result.inbound);
// Outbound: Local -> MaintainX
await this.syncOutbound(result.outbound);
return result;
}
private async syncInbound(stats: SyncStats): Promise {
const lastSync = this.syncState.get('workorders') || new Date(0);
// Fetch changes since last sync
const changes = await this.client.getWorkOrders({
updatedAfter: lastSync.toISOString(),
limit: 100,
});
for (const wo of changes.workOrders) {
const local = await this.localStore.getWorkOrder(wo.id);
if (!local) {
await this.localStore.createWorkOrder(wo);
stats.created++;
this.eventEmitter.emit('workorder:created', wo);
} else if (new Date(wo.updatedAt) > new Date(local.updatedAt)) {
await this.localStore.updateWorkOrder(wo);
stats.updated++;
this.eventEmitter.emit('workorder:updated', wo);
}
}
this.syncState.set('workorders', new Date());
}
private async syncOutbound(stats: SyncStats): Promise {
// Get pending local changes
const pendingChanges = await this.localStore.getPendingChanges();
for (const change of pendingChanges) {
try {
switch (change.action) {
case 'create':
await this.client.createWorkOrder(change.data);
stats.created++;
break;
case 'update':
// await this.client.updateWorkOrder(change.id, change.data);
stats.updated++;
break;
}
await this.localStore.markSynced(change.id);
} catch (error) {
console.error(`Failed to sync change ${change.id}:`, error);
}
}
}
// Subscribe to events
on(event: string, handler: (data: any) => void): void {
this.eventEmitter.on(event, handler);
}
}
```
### Pattern 3: Multi-Tenant Architecture
```typescript
// src/architecture/multi-tenant.ts
interface Tenant {
id: string;
name: string;
maintainxApiKey: string;
maintainxOrgId?: string;
config: TenantConfig;
}
class MultiTenantMaintainXService {
private tenantClients: Map = new Map();
private tenantStore: TenantStore;
async getClientForTenant(tenantId: string): Promise {
// Check cache
if (this.tenantClients.has(tenantId)) {
return this.tenantClients.get(tenantId)!;
}
// Load tenant config
const tenant = await this.tenantStore.getTenant(tenantId);
if (!tenant) {
throw new Error(`Tenant ${tenantId} not found`);
}
// Create client with tenant's API key
const client = new MaintainXClient({
apiKey: tenant.maintainxApiKey,
orgId: tenant.maintainxOrgId,
});
this.tenantClients.set(tenantId, client);
return client;
}
// Tenant-scoped operations
async getWorkOrdersForTenant(
tenantId: string,
params?: WorkOrderQueryParams
): Promise {
const client = await this.getClientForTenant(tenantId);
const response = await client.getWorkOrders(params);
return response.workOrders;
}
// Cross-tenant aggregation (for admin dashboards)
async getWorkOrderCountByTenant(): Promise