| name | maintainx-cost-tuning |
| description | Optimize MaintainX API usage for cost efficiency.
Use when managing API costs, optimizing request volume,
or implementing cost-effective integration patterns with MaintainX.
Trigger with phrases like "maintainx cost", "maintainx billing",
"reduce maintainx usage", "maintainx api costs", "maintainx optimization".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
MaintainX Cost Tuning
Overview
Optimize your MaintainX API usage for cost efficiency while maintaining functionality.
Prerequisites
- MaintainX integration deployed
- API usage monitoring in place
- Understanding of pricing tiers
Cost Optimization Strategies
| Strategy | Savings Potential | Implementation Effort |
|---|
| Caching | 40-60% | Low |
| Batch operations | 20-30% | Medium |
| Webhook over polling | 50-70% | Medium |
| Smart pagination | 10-20% | Low |
| Request deduplication | 15-25% | Low |
Instructions
Step 1: API Usage Tracking
interface UsageMetric {
endpoint: string;
method: string;
timestamp: Date;
responseSize: number;
cached: boolean;
}
class ApiUsageTracker {
private metrics: UsageMetric[] = [];
private dailyUsage: Map<string, number> = new Map();
track(metric: Omit<UsageMetric, 'timestamp'>): void {
this.metrics.push({
...metric,
timestamp: new Date(),
});
const today = new Date().toISOString().split('T')[0];
const key = `${today}:${metric.endpoint}`;
this.dailyUsage.set(key, (..(key) || ) + );
}
(days = ): {
now = .();
cutoff = now - days * * * * ;
recentMetrics = ..(
m..() > cutoff
);
: <, > = {};
recentMetrics.( {
byEndpoint[m.] = (byEndpoint[m.] || ) + ;
});
cacheHits = recentMetrics.( m.).;
cacheHitRate = recentMetrics. >
? cacheHits / recentMetrics.
: ;
opportunities = .(byEndpoint, cacheHitRate);
{
: ,
: recentMetrics.,
byEndpoint,
: ,
: .(recentMetrics),
opportunities,
};
}
(
: <, >,
:
): [] {
: [] = [];
.(byEndpoint).( {
(count > && !endpoint.()) {
opportunities.(
);
}
});
(cacheHitRate < ) {
opportunities.(
);
}
opportunities;
}
(: []): {
totalRequests = metrics.;
cachedRequests = metrics.( m.).;
costPerRequest = ;
savedRequests = cachedRequests;
savings = savedRequests * costPerRequest;
;
}
}
usageTracker = ();
Step 2: Smart Caching Strategy
interface CacheStrategy {
ttlSeconds: number;
staleWhileRevalidate: boolean;
priority: 'high' | 'medium' | 'low';
}
const cacheStrategies: Record<string, CacheStrategy> = {
'locations': { ttlSeconds: 3600, staleWhileRevalidate: true, priority: 'low' },
'users': { ttlSeconds: 1800, staleWhileRevalidate: true, priority: 'low' },
'assets': { ttlSeconds: 900, staleWhileRevalidate: true, priority: 'medium' },
'workorders:list': { ttlSeconds: 60, staleWhileRevalidate: true, priority: 'high' },
'workorders:single': { ttlSeconds: 300, staleWhileRevalidate: true, priority: 'medium' },
};
{
: ;
getOrFetch<T>(
: ,
: <T>,
:
): <T> {
strategy = cacheStrategies[strategyKey] || {
: ,
: ,
: ,
};
cached = ..<T>(key);
(cached) {
usageTracker.({
: strategyKey,
: ,
: ,
: ,
});
(strategy.) {
.(key, fetchFn, strategy);
}
cached;
}
data = ();
usageTracker.({
: strategyKey,
: ,
: .(data).,
: ,
});
..(key, data, strategy.);
data;
}
revalidateInBackground<T>(
: ,
: <T>,
:
): <> {
()
.( ..(key, data, strategy.))
.( .(, err));
}
}
Step 3: Webhook-Based Updates
class WebhookBasedSync {
private localCache: Map<string, any> = new Map();
constructor() {
this.initializeCache();
this.registerWebhookHandlers();
}
private async initializeCache(): Promise<void> {
console.log('Initializing local cache from MaintainX...');
const workOrders = await getAllWorkOrders(client, { status: 'OPEN' });
workOrders.forEach(wo => this.localCache.set(`workorder:${wo.id}`, wo));
console.log(`Cached ${workOrders.length} work orders`);
}
private registerWebhookHandlers(): void {
(, (event) => {
..(, event.);
});
(, (event) => {
..(, event.);
});
(, (event) => {
..();
});
}
(: ): | {
..();
}
(: ): <> {
cached = ..();
(cached) cached;
workOrder = client.(id);
..(, workOrder);
workOrder;
}
}
Step 4: Request Batching
class BatchRequestManager {
private pendingWorkOrderIds: Set<string> = new Set();
private batchTimeout: NodeJS.Timeout | null = null;
private batchResolvers: Map<string, (wo: WorkOrder) => void> = new Map();
async getWorkOrder(id: string): Promise<WorkOrder> {
return new Promise((resolve) => {
this.pendingWorkOrderIds.add(id);
this.batchResolvers.set(id, resolve);
if (!this.batchTimeout) {
this.batchTimeout = setTimeout(() => .(), );
}
});
}
(): <> {
ids = .(.);
..();
. = ;
(ids. === ) ;
.();
workOrders = .(
ids.( client.(id))
);
workOrders.( {
resolver = ..(ids[i]);
(resolver) {
(wo);
..(ids[i]);
}
});
}
}
Step 5: Efficient Data Fetching
async function fetchMinimalWorkOrderData(
client: MaintainXClient,
params: WorkOrderQueryParams
): Promise<WorkOrderSummary[]> {
const response = await client.getWorkOrders({
...params,
limit: params.limit || 50,
});
return response.workOrders.map(wo => ({
id: wo.id,
title: wo.title,
status: wo.status,
priority: wo.priority,
dueDate: wo.dueDate,
}));
}
async function fetchUntilCondition(
client: MaintainXClient,
condition: (wo: WorkOrder) => boolean,
params: WorkOrderQueryParams = {}
): <[]> {
: [] = [];
: | ;
{
response = client.({ ...params, cursor, : });
( wo response.) {
((wo)) {
results.(wo);
} {
results;
}
}
cursor = response. || ;
} (cursor && results. < );
results;
}
Step 6: Cost Dashboard
interface CostReport {
period: string;
totalRequests: number;
estimatedCost: number;
byEndpoint: Record<string, { count: number; cost: number }>;
recommendations: string[];
}
function generateCostReport(days = 30): CostReport {
const usage = usageTracker.getUsageReport(days);
const costPerRequest = 0.001;
const byEndpoint: Record<string, { count: number; cost: number }> = {};
Object.entries(usage.byEndpoint).forEach(([endpoint, count]) => {
byEndpoint[endpoint] = {
count: count as number,
cost: (count as number) * costPerRequest,
};
});
const sortedEndpoints = .(byEndpoint)
.( b[]. - a[].);
: [] = [];
(sortedEndpoints. > ) {
[topEndpoint, topUsage] = sortedEndpoints[];
recommendations.(
+
);
}
cacheHitRate = (usage.);
(cacheHitRate < ) {
potentialSavings = usage. * * costPerRequest;
recommendations.(
+
);
}
{
: ,
: usage.,
: usage. * costPerRequest,
byEndpoint,
recommendations,
};
}
Output
- API usage tracking implemented
- Smart caching strategy
- Webhook-based sync instead of polling
- Request batching
- Cost dashboard and reports
Cost Savings Summary
| Optimization | Before | After | Savings |
|---|
| Caching | 10,000/day | 4,000/day | 60% |
| Webhooks vs polling | 2,880/day | 100/day | 97% |
| Batching | 500/day | 100/day | 80% |
| Total estimate | 13,380/day | 4,200/day | 69% |
Resources
Next Steps
For architecture patterns, see maintainx-reference-architecture.