[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F8444PBD788STJ352K22CB":3,"skill-same:01M6F8444PBD788STJ352K22CB":73},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":50,"commitSha":51,"skillDirectory":52,"forksCount":53,"repositoryHtmlUrl":54,"repositoryHomepageUrl":6,"ownerHtmlUrl":55,"ownerBlogUrl":56,"ownerDescription":57,"updatedAt":58,"install":59,"resources":72},"01M6F8444PBD788STJ352K22CB","maintainx-performance-tuning",null,"Optimize MaintainX API integration performance.\nUse when experiencing slow API responses, optimizing data fetching,\nor improving integration throughput with MaintainX.\nTrigger with phrases like \"maintainx performance\", \"maintainx slow\",\n\"optimize maintainx\", \"maintainx caching\", \"maintainx faster\".","Dicklesworthstone\u002Fpi_agent_rust","Dicklesworthstone","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F35050222?v=4","01M6CG26AR942CSVMN1M5E3DSE","Jeff Emanuel","01M6CG26EPP71PSHW1VDS71121",1986,"MIT","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fmaintainx-pack\u002Fskills\u002Fmaintainx-performance-tuning\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"maintainx performance tuning","tuning","performance tuning","performance","api integration","when","data fetching","with","throughput","trigger","io","caching","optimize","use","edit","write","read","Bash","api","data","integration","npm","2026-11-10 10:12:30",false,"---\nname: maintainx-performance-tuning\ndescription: |\n  Optimize MaintainX API integration performance.\n  Use when experiencing slow API responses, optimizing data fetching,\n  or improving integration throughput with MaintainX.\n  Trigger with phrases like \"maintainx performance\", \"maintainx slow\",\n  \"optimize maintainx\", \"maintainx caching\", \"maintainx faster\".\nallowed-tools: Read, Write, Edit, Bash(npm:*)\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\n---\n\n# MaintainX Performance Tuning\n\n## Overview\n\nOptimize your MaintainX integration for maximum performance with caching, efficient queries, and connection pooling.\n\n## Prerequisites\n\n- MaintainX integration working\n- Redis or in-memory cache available\n- Performance metrics baseline\n\n## Performance Metrics Baseline\n\n| Operation | Target | Acceptable |\n|-----------|--------|------------|\n| List work orders | \u003C500ms | \u003C1000ms |\n| Get single work order | \u003C200ms | \u003C500ms |\n| Create work order | \u003C500ms | \u003C1000ms |\n| Paginated fetch (100 items) | \u003C1000ms | \u003C2000ms |\n\n## Instructions\n\n### Step 1: Response Caching\n\n```typescript\n\u002F\u002F src\u002Fcache\u002Fcache-manager.ts\nimport { Redis } from 'ioredis';\n\ninterface CacheConfig {\n  ttlSeconds: number;\n  prefix: string;\n}\n\nclass CacheManager {\n  private redis: Redis;\n  private prefix: string;\n\n  constructor(redisUrl: string, prefix = 'maintainx') {\n    this.redis = new Redis(redisUrl);\n    this.prefix = prefix;\n  }\n\n  private key(key: string): string {\n    return `${this.prefix}:${key}`;\n  }\n\n  async get\u003CT>(key: string): Promise\u003CT | null> {\n    const data = await this.redis.get(this.key(key));\n    if (!data) return null;\n\n    return JSON.parse(data) as T;\n  }\n\n  async set\u003CT>(key: string, value: T, ttlSeconds = 300): Promise\u003Cvoid> {\n    await this.redis.set(\n      this.key(key),\n      JSON.stringify(value),\n      'EX',\n      ttlSeconds\n    );\n  }\n\n  async delete(key: string): Promise\u003Cvoid> {\n    await this.redis.del(this.key(key));\n  }\n\n  async invalidatePattern(pattern: string): Promise\u003Cvoid> {\n    const keys = await this.redis.keys(this.key(pattern));\n    if (keys.length > 0) {\n      await this.redis.del(...keys);\n    }\n  }\n}\n\n\u002F\u002F Cached API client wrapper\nclass CachedMaintainXClient {\n  private client: MaintainXClient;\n  private cache: CacheManager;\n\n  constructor(client: MaintainXClient, cache: CacheManager) {\n    this.client = client;\n    this.cache = cache;\n  }\n\n  async getWorkOrder(id: string): Promise\u003CWorkOrder> {\n    const cacheKey = `workorder:${id}`;\n\n    \u002F\u002F Check cache first\n    const cached = await this.cache.get\u003CWorkOrder>(cacheKey);\n    if (cached) {\n      console.log(`Cache hit: ${cacheKey}`);\n      return cached;\n    }\n\n    \u002F\u002F Fetch from API\n    const workOrder = await this.client.getWorkOrder(id);\n\n    \u002F\u002F Cache for 5 minutes\n    await this.cache.set(cacheKey, workOrder, 300);\n\n    return workOrder;\n  }\n\n  async getWorkOrders(params?: WorkOrderQueryParams): Promise\u003CWorkOrderListResponse> {\n    \u002F\u002F Cache list queries for shorter duration\n    const cacheKey = `workorders:${JSON.stringify(params || {})}`;\n\n    const cached = await this.cache.get\u003CWorkOrderListResponse>(cacheKey);\n    if (cached) {\n      return cached;\n    }\n\n    const response = await this.client.getWorkOrders(params);\n    await this.cache.set(cacheKey, response, 60);  \u002F\u002F 1 minute\n\n    return response;\n  }\n\n  async createWorkOrder(data: CreateWorkOrderInput): Promise\u003CWorkOrder> {\n    const workOrder = await this.client.createWorkOrder(data);\n\n    \u002F\u002F Invalidate list cache\n    await this.cache.invalidatePattern('workorders:*');\n\n    return workOrder;\n  }\n\n  \u002F\u002F Invalidate cache when data changes\n  async invalidateWorkOrder(id: string): Promise\u003Cvoid> {\n    await this.cache.delete(`workorder:${id}`);\n    await this.cache.invalidatePattern('workorders:*');\n  }\n}\n```\n\n### Step 2: Connection Pooling\n\n```typescript\n\u002F\u002F src\u002Fapi\u002Fconnection-pool.ts\nimport axios, { AxiosInstance } from 'axios';\nimport https from 'https';\nimport http from 'http';\n\nfunction createOptimizedClient(): AxiosInstance {\n  \u002F\u002F HTTP agent with keep-alive\n  const httpsAgent = new https.Agent({\n    keepAlive: true,\n    keepAliveMsecs: 30000,\n    maxSockets: 50,\n    maxFreeSockets: 10,\n    timeout: 30000,\n  });\n\n  const httpAgent = new http.Agent({\n    keepAlive: true,\n    keepAliveMsecs: 30000,\n    maxSockets: 50,\n    maxFreeSockets: 10,\n    timeout: 30000,\n  });\n\n  return axios.create({\n    baseURL: 'https:\u002F\u002Fapi.getmaintainx.com\u002Fv1',\n    timeout: 30000,\n    httpsAgent,\n    httpAgent,\n    headers: {\n      'Authorization': `Bearer ${process.env.MAINTAINX_API_KEY}`,\n      'Content-Type': 'application\u002Fjson',\n      'Connection': 'keep-alive',\n    },\n    \u002F\u002F Response compression\n    decompress: true,\n  });\n}\n\nexport { createOptimizedClient };\n```\n\n### Step 3: Efficient Pagination\n\n```typescript\n\u002F\u002F src\u002Futils\u002Fefficient-pagination.ts\n\ninterface EfficientPaginationOptions {\n  batchSize: number;\n  maxConcurrent: number;\n  delayBetweenBatches: number;\n}\n\n\u002F\u002F Stream-based pagination for memory efficiency\nasync function* streamWorkOrders(\n  client: MaintainXClient,\n  params: WorkOrderQueryParams = {},\n  options: Partial\u003CEfficientPaginationOptions> = {}\n): AsyncGenerator\u003CWorkOrder, void, unknown> {\n  const { batchSize = 100 } = options;\n  let cursor: string | undefined;\n\n  do {\n    const response = await client.getWorkOrders({\n      ...params,\n      cursor,\n      limit: batchSize,\n    });\n\n    for (const workOrder of response.workOrders) {\n      yield workOrder;\n    }\n\n    cursor = response.nextCursor || undefined;\n  } while (cursor);\n}\n\n\u002F\u002F Parallel fetch with cursor prefetch\nasync function fetchAllWorkOrdersOptimized(\n  client: MaintainXClient,\n  params: WorkOrderQueryParams = {}\n): Promise\u003CWorkOrder[]> {\n  const allWorkOrders: WorkOrder[] = [];\n  let cursor: string | undefined;\n  let prefetchPromise: Promise\u003CWorkOrderListResponse> | null = null;\n\n  do {\n    \u002F\u002F Use prefetched response if available\n    let response: WorkOrderListResponse;\n    if (prefetchPromise) {\n      response = await prefetchPromise;\n    } else {\n      response = await client.getWorkOrders({ ...params, cursor, limit: 100 });\n    }\n\n    allWorkOrders.push(...response.workOrders);\n    cursor = response.nextCursor || undefined;\n\n    \u002F\u002F Prefetch next page while processing current\n    if (cursor) {\n      prefetchPromise = client.getWorkOrders({ ...params, cursor, limit: 100 });\n    } else {\n      prefetchPromise = null;\n    }\n  } while (cursor);\n\n  return allWorkOrders;\n}\n\n\u002F\u002F Usage with memory-efficient streaming\nasync function processLargeDataset(client: MaintainXClient) {\n  let processed = 0;\n\n  for await (const workOrder of streamWorkOrders(client, { status: 'DONE' })) {\n    \u002F\u002F Process one at a time - no memory buildup\n    await processWorkOrder(workOrder);\n    processed++;\n\n    if (processed % 100 === 0) {\n      console.log(`Processed ${processed} work orders`);\n    }\n  }\n}\n```\n\n### Step 4: Request Deduplication\n\n```typescript\n\u002F\u002F src\u002Futils\u002Fdeduplication.ts\n\nclass RequestDeduplicator {\n  private pending: Map\u003Cstring, Promise\u003Cany>> = new Map();\n\n  async dedupe\u003CT>(key: string, operation: () => Promise\u003CT>): Promise\u003CT> {\n    \u002F\u002F Check for in-flight request\n    if (this.pending.has(key)) {\n      console.log(`Deduplicating request: ${key}`);\n      return this.pending.get(key) as Promise\u003CT>;\n    }\n\n    \u002F\u002F Create new request\n    const promise = operation().finally(() => {\n      this.pending.delete(key);\n    });\n\n    this.pending.set(key, promise);\n    return promise;\n  }\n}\n\n\u002F\u002F Usage in client\nclass DeduplicatedMaintainXClient {\n  private client: MaintainXClient;\n  private deduper: RequestDeduplicator;\n\n  constructor(client: MaintainXClient) {\n    this.client = client;\n    this.deduper = new RequestDeduplicator();\n  }\n\n  async getWorkOrder(id: string): Promise\u003CWorkOrder> {\n    return this.deduper.dedupe(\n      `workorder:${id}`,\n      () => this.client.getWorkOrder(id)\n    );\n  }\n\n  async getAsset(id: string): Promise\u003CAsset> {\n    return this.deduper.dedupe(\n      `asset:${id}`,\n      () => this.client.getAsset(id)\n    );\n  }\n}\n```\n\n### Step 5: Batch Data Loading\n\n```typescript\n\u002F\u002F src\u002Futils\u002Fdataloader.ts\nimport DataLoader from 'dataloader';\n\n\u002F\u002F Batch load work orders\nconst workOrderLoader = new DataLoader\u003Cstring, WorkOrder>(\n  async (ids: readonly string[]) => {\n    console.log(`Batch loading ${ids.length} work orders`);\n\n    \u002F\u002F Fetch all in parallel (or single batch request if API supports)\n    const workOrders = await Promise.all(\n      ids.map(id => client.getWorkOrder(id))\n    );\n\n    \u002F\u002F Return in same order as input\n    return workOrders;\n  },\n  {\n    maxBatchSize: 20,\n    batchScheduleFn: (callback) => setTimeout(callback, 10),  \u002F\u002F 10ms batching window\n    cache: true,\n  }\n);\n\n\u002F\u002F Batch load assets\nconst assetLoader = new DataLoader\u003Cstring, Asset>(\n  async (ids: readonly string[]) => {\n    const assets = await Promise.all(\n      ids.map(id => client.getAsset(id))\n    );\n    return assets;\n  }\n);\n\n\u002F\u002F Usage: multiple calls get batched\nasync function loadWorkOrdersWithAssets(workOrderIds: string[]) {\n  \u002F\u002F These will be batched into fewer API calls\n  const workOrders = await Promise.all(\n    workOrderIds.map(id => workOrderLoader.load(id))\n  );\n\n  \u002F\u002F Load associated assets\n  const assetIds = workOrders\n    .map(wo => wo.assetId)\n    .filter(Boolean) as string[];\n\n  const assets = await Promise.all(\n    assetIds.map(id => assetLoader.load(id))\n  );\n\n  return { workOrders, assets };\n}\n```\n\n### Step 6: Performance Monitoring\n\n```typescript\n\u002F\u002F src\u002Fmonitoring\u002Fperformance.ts\nimport { performance } from 'perf_hooks';\n\ninterface PerformanceMetric {\n  operation: string;\n  duration: number;\n  timestamp: Date;\n  success: boolean;\n}\n\nclass PerformanceMonitor {\n  private metrics: PerformanceMetric[] = [];\n\n  async measure\u003CT>(\n    operation: string,\n    fn: () => Promise\u003CT>\n  ): Promise\u003CT> {\n    const start = performance.now();\n    let success = true;\n\n    try {\n      return await fn();\n    } catch (error) {\n      success = false;\n      throw error;\n    } finally {\n      const duration = performance.now() - start;\n\n      this.metrics.push({\n        operation,\n        duration,\n        timestamp: new Date(),\n        success,\n      });\n\n      \u002F\u002F Log slow operations\n      if (duration > 1000) {\n        console.warn(`Slow operation: ${operation} took ${duration.toFixed(0)}ms`);\n      }\n    }\n  }\n\n  getStats(operation?: string): any {\n    const filtered = operation\n      ? this.metrics.filter(m => m.operation === operation)\n      : this.metrics;\n\n    if (filtered.length === 0) return null;\n\n    const durations = filtered.map(m => m.duration);\n\n    return {\n      count: filtered.length,\n      avg: durations.reduce((a, b) => a + b, 0) \u002F durations.length,\n      min: Math.min(...durations),\n      max: Math.max(...durations),\n      p95: percentile(durations, 95),\n      p99: percentile(durations, 99),\n      successRate: filtered.filter(m => m.success).length \u002F filtered.length,\n    };\n  }\n}\n\nfunction percentile(arr: number[], p: number): number {\n  const sorted = [...arr].sort((a, b) => a - b);\n  const index = Math.ceil((p \u002F 100) * sorted.length) - 1;\n  return sorted[index];\n}\n\n\u002F\u002F Usage\nconst monitor = new PerformanceMonitor();\n\nconst workOrders = await monitor.measure(\n  'getWorkOrders',\n  () => client.getWorkOrders({ limit: 100 })\n);\n\nconsole.log('Performance stats:', monitor.getStats('getWorkOrders'));\n```\n\n## Output\n\n- Caching layer implemented\n- Connection pooling configured\n- Efficient pagination patterns\n- Request deduplication\n- DataLoader for batch loading\n- Performance monitoring\n\n## Performance Checklist\n\n- [ ] Response caching configured\n- [ ] Connection pooling enabled\n- [ ] Pagination uses streaming where appropriate\n- [ ] Duplicate requests deduplicated\n- [ ] Batch loading for related data\n- [ ] Performance metrics collected\n- [ ] Slow operations identified and optimized\n\n## Resources\n\n- [MaintainX API Documentation](https:\u002F\u002Fmaintainx.dev\u002F)\n- [DataLoader Documentation](https:\u002F\u002Fgithub.com\u002Fgraphql\u002Fdataloader)\n- [Node.js Performance Best Practices](https:\u002F\u002Fnodejs.org\u002Fen\u002Fdocs\u002Fguides\u002Fdont-block-the-event-loop)\n\n## Next Steps\n\nFor cost optimization, see `maintainx-cost-tuning`.\n","# MaintainX Performance Tuning\n\n## Overview\n\nOptimize your MaintainX integration for maximum performance with caching, efficient queries, and connection pooling.\n\n## Prerequisites\n\n- MaintainX integration working\n- Redis or in-memory cache available\n- Performance metrics baseline\n\n## Performance Metrics Baseline\n\n| Operation | Target | Acceptable |\n|-----------|--------|------------|\n| List work orders | \u003C500ms | \u003C1000ms |\n| Get single work order | \u003C200ms | \u003C500ms |\n| Create work order | \u003C500ms | \u003C1000ms |\n| Paginated fetch (100 items) | \u003C1000ms | \u003C2000ms |\n\n## Instructions\n\n### Step 1: Response Caching\n\n```typescript\n\u002F\u002F src\u002Fcache\u002Fcache-manager.ts\nimport { Redis } from 'ioredis';\n\ninterface CacheConfig {\n  ttlSeconds: number;\n  prefix: string;\n}\n\nclass CacheManager {\n  private redis: Redis;\n  private prefix: string;\n\n  constructor(redisUrl: string, prefix = 'maintainx') {\n    this.redis = new Redis(redisUrl);\n    this.prefix = prefix;\n  }\n\n  private key(key: string): string {\n    return `${this.prefix}:${key}`;\n  }\n\n  async get\u003CT>(key: string): Promise\u003CT | null> {\n    const data = await this.redis.get(this.key(key));\n    if (!data) return null;\n\n    return JSON.parse(data) as T;\n  }\n\n  async set\u003CT>(key: string, value: T, ttlSeconds = 300): Promise\u003Cvoid> {\n    await this.redis.set(\n      this.key(key),\n      JSON.stringify(value),\n      'EX',\n      ttlSeconds\n    );\n  }\n\n  async delete(key: string): Promise\u003Cvoid> {\n    await this.redis.del(this.key(key));\n  }\n\n  async invalidatePattern(pattern: string): Promise\u003Cvoid> {\n    const keys = await this.redis.keys(this.key(pattern));\n    if (keys.length > 0) {\n      await this.redis.del(...keys);\n    }\n  }\n}\n\n\u002F\u002F Cached API client wrapper\nclass CachedMaintainXClient {\n  private client: MaintainXClient;\n  private cache: CacheManager;\n\n  constructor(client: MaintainXClient, cache: CacheManager) {\n    this.client = client;\n    this.cache = cache;\n  }\n\n  async getWorkOrder(id: string): Promise\u003CWorkOrder> {\n    const cacheKey = `workorder:${id}`;\n\n    \u002F\u002F Check cache first\n    const cached = await this.cache.get\u003CWorkOrder>(cacheKey);\n    if (cached) {\n      console.log(`Cache hit: ${cacheKey}`);\n      return cached;\n    }\n\n    \u002F\u002F Fetch from API\n    const workOrder = await this.client.getWorkOrder(id);\n\n    \u002F\u002F Cache for 5 minutes\n    await this.cache.set(cacheKey, workOrder, 300);\n\n    return workOrder;\n  }\n\n  async getWorkOrders(params?: WorkOrderQueryParams): Promise\u003CWorkOrderListResponse> {\n    \u002F\u002F Cache list queries for shorter duration\n    const cacheKey = `workorders:${JSON.stringify(params || {})}`;\n\n    const cached = await this.cache.get\u003CWorkOrderListResponse>(cacheKey);\n    if (cached) {\n      return cached;\n    }\n\n    const response = await this.client.getWorkOrders(params);\n    await this.cache.set(cacheKey, response, 60);  \u002F\u002F 1 minute\n\n    return response;\n  }\n\n  async createWorkOrder(data: CreateWorkOrderInput): Promise\u003CWorkOrder> {\n    const workOrder = await this.client.createWorkOrder(data);\n\n    \u002F\u002F Invalidate list cache\n    await this.cache.invalidatePattern('workorders:*');\n\n    return workOrder;\n  }\n\n  \u002F\u002F Invalidate cache when data changes\n  async invalidateWorkOrder(id: string): Promise\u003Cvoid> {\n    await this.cache.delete(`workorder:${id}`);\n    await this.cache.invalidatePattern('workorders:*');\n  }\n}\n```\n\n### Step 2: Connection Pooling\n\n```typescript\n\u002F\u002F src\u002Fapi\u002Fconnection-pool.ts\nimport axios, { AxiosInstance } from 'axios';\nimport https from 'https';\nimport http from 'http';\n\nfunction createOptimizedClient(): AxiosInstance {\n  \u002F\u002F HTTP agent with keep-alive\n  const httpsAgent = new https.Agent({\n    keepAlive: true,\n    keepAliveMsecs: 30000,\n    maxSockets: 50,\n    maxFreeSockets: 10,\n    timeout: 30000,\n  });\n\n  const httpAgent = new http.Agent({\n    keepAlive: true,\n    keepAliveMsecs: 30000,\n    maxSockets: 50,\n    maxFreeSockets: 10,\n    timeout: 30000,\n  });\n\n  return axios.create({\n    baseURL: 'https:\u002F\u002Fapi.getmaintainx.com\u002Fv1',\n    timeout: 30000,\n    httpsAgent,\n    httpAgent,\n    headers: {\n      'Authorization': `Bearer ${process.env.MAINTAINX_API_KEY}`,\n      'Content-Type': 'application\u002Fjson',\n      'Connection': 'keep-alive',\n    },\n    \u002F\u002F Response compression\n    decompress: true,\n  });\n}\n\nexport { createOptimizedClient };\n```\n\n### Step 3: Efficient Pagination\n\n```typescript\n\u002F\u002F src\u002Futils\u002Fefficient-pagination.ts\n\ninterface EfficientPaginationOptions {\n  batchSize: number;\n  maxConcurrent: number;\n  delayBetweenBatches: number;\n}\n\n\u002F\u002F Stream-based pagination for memory efficiency\nasync function* streamWorkOrders(\n  client: MaintainXClient,\n  params: WorkOrderQueryParams = {},\n  options: Partial\u003CEfficientPaginationOptions> = {}\n): AsyncGenerator\u003CWorkOrder, void, unknown> {\n  const { batchSize = 100 } = options;\n  let cursor: string | undefined;\n\n  do {\n    const response = await client.getWorkOrders({\n      ...params,\n      cursor,\n      limit: batchSize,\n    });\n\n    for (const workOrder of response.workOrders) {\n      yield workOrder;\n    }\n\n    cursor = response.nextCursor || undefined;\n  } while (cursor);\n}\n\n\u002F\u002F Parallel fetch with cursor prefetch\nasync function fetchAllWorkOrdersOptimized(\n  client: MaintainXClient,\n  params: WorkOrderQueryParams = {}\n): Promise\u003CWorkOrder[]> {\n  const allWorkOrders: WorkOrder[] = [];\n  let cursor: string | undefined;\n  let prefetchPromise: Promise\u003CWorkOrderListResponse> | null = null;\n\n  do {\n    \u002F\u002F Use prefetched response if available\n    let response: WorkOrderListResponse;\n    if (prefetchPromise) {\n      response = await prefetchPromise;\n    } else {\n      response = await client.getWorkOrders({ ...params, cursor, limit: 100 });\n    }\n\n    allWorkOrders.push(...response.workOrders);\n    cursor = response.nextCursor || undefined;\n\n    \u002F\u002F Prefetch next page while processing current\n    if (cursor) {\n      prefetchPromise = client.getWorkOrders({ ...params, cursor, limit: 100 });\n    } else {\n      prefetchPromise = null;\n    }\n  } while (cursor);\n\n  return allWorkOrders;\n}\n\n\u002F\u002F Usage with memory-efficient streaming\nasync function processLargeDataset(client: MaintainXClient) {\n  let processed = 0;\n\n  for await (const workOrder of streamWorkOrders(client, { status: 'DONE' })) {\n    \u002F\u002F Process one at a time - no memory buildup\n    await processWorkOrder(workOrder);\n    processed++;\n\n    if (processed % 100 === 0) {\n      console.log(`Processed ${processed} work orders`);\n    }\n  }\n}\n```\n\n### Step 4: Request Deduplication\n\n```typescript\n\u002F\u002F src\u002Futils\u002Fdeduplication.ts\n\nclass RequestDeduplicator {\n  private pending: Map\u003Cstring, Promise\u003Cany>> = new Map();\n\n  async dedupe\u003CT>(key: string, operation: () => Promise\u003CT>): Promise\u003CT> {\n    \u002F\u002F Check for in-flight request\n    if (this.pending.has(key)) {\n      console.log(`Deduplicating request: ${key}`);\n      return this.pending.get(key) as Promise\u003CT>;\n    }\n\n    \u002F\u002F Create new request\n    const promise = operation().finally(() => {\n      this.pending.delete(key);\n    });\n\n    this.pending.set(key, promise);\n    return promise;\n  }\n}\n\n\u002F\u002F Usage in client\nclass DeduplicatedMaintainXClient {\n  private client: MaintainXClient;\n  private deduper: RequestDeduplicator;\n\n  constructor(client: MaintainXClient) {\n    this.client = client;\n    this.deduper = new RequestDeduplicator();\n  }\n\n  async getWorkOrder(id: string): Promise\u003CWorkOrder> {\n    return this.deduper.dedupe(\n      `workorder:${id}`,\n      () => this.client.getWorkOrder(id)\n    );\n  }\n\n  async getAsset(id: string): Promise\u003CAsset> {\n    return this.deduper.dedupe(\n      `asset:${id}`,\n      () => this.client.getAsset(id)\n    );\n  }\n}\n```\n\n### Step 5: Batch Data Loading\n\n```typescript\n\u002F\u002F src\u002Futils\u002Fdataloader.ts\nimport DataLoader from 'dataloader';\n\n\u002F\u002F Batch load work orders\nconst workOrderLoader = new DataLoader\u003Cstring, WorkOrder>(\n  async (ids: readonly string[]) => {\n    console.log(`Batch loading ${ids.length} work orders`);\n\n    \u002F\u002F Fetch all in parallel (or single batch request if API supports)\n    const workOrders = await Promise.all(\n      ids.map(id => client.getWorkOrder(id))\n    );\n\n    \u002F\u002F Return in same order as input\n    return workOrders;\n  },\n  {\n    maxBatchSize: 20,\n    batchScheduleFn: (callback) => setTimeout(callback, 10),  \u002F\u002F 10ms batching window\n    cache: true,\n  }\n);\n\n\u002F\u002F Batch load assets\nconst assetLoader = new DataLoader\u003Cstring, Asset>(\n  async (ids: readonly string[]) => {\n    const assets = await Promise.all(\n      ids.map(id => client.getAsset(id))\n    );\n    return assets;\n  }\n);\n\n\u002F\u002F Usage: multiple calls get batched\nasync function loadWorkOrdersWithAssets(workOrderIds: string[]) {\n  \u002F\u002F These will be batched into fewer API calls\n  const workOrders = await Promise.all(\n    workOrderIds.map(id => workOrderLoader.load(id))\n  );\n\n  \u002F\u002F Load associated assets\n  const assetIds = workOrders\n    .map(wo => wo.assetId)\n    .filter(Boolean) as string[];\n\n  const assets = await Promise.all(\n    assetIds.map(id => assetLoader.load(id))\n  );\n\n  return { workOrders, assets };\n}\n```\n\n### Step 6: Performance Monitoring\n\n```typescript\n\u002F\u002F src\u002Fmonitoring\u002Fperformance.ts\nimport { performance } from 'perf_hooks';\n\ninterface PerformanceMetric {\n  operation: string;\n  duration: number;\n  timestamp: Date;\n  success: boolean;\n}\n\nclass PerformanceMonitor {\n  private metrics: PerformanceMetric[] = [];\n\n  async measure\u003CT>(\n    operation: string,\n    fn: () => Promise\u003CT>\n  ): Promise\u003CT> {\n    const start = performance.now();\n    let success = true;\n\n    try {\n      return await fn();\n    } catch (error) {\n      success = false;\n      throw error;\n    } finally {\n      const duration = performance.now() - start;\n\n      this.metrics.push({\n        operation,\n        duration,\n        timestamp: new Date(),\n        success,\n      });\n\n      \u002F\u002F Log slow operations\n      if (duration > 1000) {\n        console.warn(`Slow operation: ${operation} took ${duration.toFixed(0)}ms`);\n      }\n    }\n  }\n\n  getStats(operation?: string): any {\n    const filtered = operation\n      ? this.metrics.filter(m => m.operation === operation)\n      : this.metrics;\n\n    if (filtered.length === 0) return null;\n\n    const durations = filtered.map(m => m.duration);\n\n    return {\n      count: filtered.length,\n      avg: durations.reduce((a, b) => a + b, 0) \u002F durations.length,\n      min: Math.min(...durations),\n      max: Math.max(...durations),\n      p95: percentile(durations, 95),\n      p99: percentile(durations, 99),\n      successRate: filtered.filter(m => m.success).length \u002F filtered.length,\n    };\n  }\n}\n\nfunction percentile(arr: number[], p: number): number {\n  const sorted = [...arr].sort((a, b) => a - b);\n  const index = Math.ceil((p \u002F 100) * sorted.length) - 1;\n  return sorted[index];\n}\n\n\u002F\u002F Usage\nconst monitor = new PerformanceMonitor();\n\nconst workOrders = await monitor.measure(\n  'getWorkOrders',\n  () => client.getWorkOrders({ limit: 100 })\n);\n\nconsole.log('Performance stats:', monitor.getStats('getWorkOrders'));\n```\n\n## Output\n\n- Caching layer implemented\n- Connection pooling configured\n- Efficient pagination patterns\n- Request deduplication\n- DataLoader for batch loading\n- Performance monitoring\n\n## Performance Checklist\n\n- [ ] Response caching configured\n- [ ] Connection pooling enabled\n- [ ] Pagination uses streaming where appropriate\n- [ ] Duplicate requests deduplicated\n- [ ] Batch loading for related data\n- [ ] Performance metrics collected\n- [ ] Slow operations identified and optimized\n\n## Resources\n\n- [MaintainX API Documentation](https:\u002F\u002Fmaintainx.dev\u002F)\n- [DataLoader Documentation](https:\u002F\u002Fgithub.com\u002Fgraphql\u002Fdataloader)\n- [Node.js Performance Best Practices](https:\u002F\u002Fnodejs.org\u002Fen\u002Fdocs\u002Fguides\u002Fdont-block-the-event-loop)\n\n## Next Steps\n\nFor cost optimization, see `maintainx-cost-tuning`.\n",{"name":5,"author":46,"license":15,"version":47,"description":48,"allowed-tools":49},"Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Optimize MaintainX API integration performance.\nUse when experiencing slow API responses, optimizing data fetching,\nor improving integration throughput with MaintainX.\nTrigger with phrases like \"maintainx performance\", \"maintainx slow\",\n\"optimize maintainx\", \"maintainx caching\", \"maintainx faster\".\n","Read, Write, Edit, Bash(npm:*)","main","90b50ed0778745a80fd5bfb13b1843d45b9e82f7","tests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fmaintainx-pack\u002Fskills\u002Fmaintainx-performance-tuning",233,"https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust","https:\u002F\u002Fgithub.com\u002FDicklesworthstone","https:\u002F\u002Fwww.jeffreyemanuel.com\u002F","Building in NY","2026-11-13 03:33:43",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add Dicklesworthstone\u002Fpi_agent_rust --skill maintainx-performance-tuning",{"tool":65,"command":66},"bunx","bunx skills add Dicklesworthstone\u002Fpi_agent_rust --skill maintainx-performance-tuning",{"tool":68,"command":69},"pnpm","pnpm dlx skills add Dicklesworthstone\u002Fpi_agent_rust --skill maintainx-performance-tuning","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fmaintainx-pack\u002Fskills\u002Fmaintainx-performance-tuning\u002FSKILL.md",true,[],[74,114,138,163,190,212],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":78,"licenseFileUrl":79,"sourceHtmlUrl":80,"categories":81,"keywords":87,"publishedAt":41},"01M6FEGPPK0ZTKCCM0R3E3KS33","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FSKILL.md",[82],{"categoryNo":83,"categoryName":84,"taxonomyType":85,"taxonomyTypeDesc":86},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,32,106,107,108,109,110,111,112,113],"web artifacts builder","web","artifacts","artifacts builder","builder","frontend","css","components","react","component","routing","state management","state","shadcn","file","ui","Tools","Tailwind","html","single-file","simple","ui components","multi","for","jsx","suite",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":78,"licenseFileUrl":118,"sourceHtmlUrl":119,"categories":120,"keywords":125,"publishedAt":41},"01M6FEE9VTK1W4GY21AKREJXRG","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FSKILL.md",[121,124],{"categoryNo":122,"categoryName":123,"taxonomyType":85,"taxonomyTypeDesc":86},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":83,"categoryName":84,"taxonomyType":85,"taxonomyTypeDesc":86},[126,127,128,93,129,130,89,131,132,133,103,134,135,136,137,26,111],"testing","webapp testing","webapp","screenshots","playwright","debugging","toolkit","browser","logs","applications","behavior","local",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":142,"sourceHtmlUrl":143,"categories":144,"keywords":145,"publishedAt":41},"01M6FE20F7ZTQBFWKF4MPJ2SBX","neuropixels-analysis","Neuropixels neural recording analysis. Load SpikeGLX\u002FOpenEphys data, preprocess, motion correction, Kilosort4 spike sorting, quality metrics, Allen\u002FIBL curation, AI-assisted visual analysis, for Neuropixels 1.0\u002F2.0 extracellular electrophysiology. Use when working with neural recordings, spike sorting, extracellular electrophysiology, or when the user mentions Neuropixels, SpikeGLX, Open Ephys, Kilosort, quality metrics, or unit curation.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FSKILL.md",[],[146,147,148,149,38,150,151,152,32,153,154,155,156,157,158,159,26,160,161,162,111,24],"analysis","neuropixels analysis","spike","metrics","open","quality","user","recordings","Neural","motion","visual","quality metrics","unit","sorting","curation","recording","load",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":78,"licenseFileUrl":167,"sourceHtmlUrl":168,"categories":169,"keywords":173,"publishedAt":41},"01M6FDP0PDK6F1GGX395C7625Z","skill-creator","Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FSKILL.md",[170],{"categoryNo":171,"categoryName":172,"taxonomyType":85,"taxonomyTypeDesc":86},"01JBSEEDCAT000000000000023","Skill与智能体开发",[174,175,176,177,178,179,180,181,182,183,184,185,186,187,26,111,188,24,189],"skill creator","creator","workflows","create","update","capabilities","knowledge","tool","integrations","specialized","guide","new skill","existing skill","users","Existing","new",{"skillNo":191,"name":192,"nameZh":6,"description":193,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":194,"sourceHtmlUrl":195,"categories":196,"keywords":198,"publishedAt":41},"01M6FDM8Y7VK7NYG9SM7QPA3PW","notebooklm","Use this skill to query your Google NotebookLM notebooks directly from Claude Code for source-grounded, citation-backed answers from Gemini. Browser automation, library management, persistent auth. Drastically reduced hallucinations through document-only responses.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FSKILL.md",[197],{"categoryNo":171,"categoryName":172,"taxonomyType":85,"taxonomyTypeDesc":86},[192,199,200,201,202,203,204,133,205,206,32,207,208,209,210,111,211],"google","browser automation","gemini","automation","auth","code","library","management","only","document","query","Citation","source",{"skillNo":213,"name":214,"nameZh":6,"description":215,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":78,"licenseFileUrl":216,"sourceHtmlUrl":217,"categories":218,"keywords":225,"publishedAt":41},"01M6FDHPXE10J3XGTCH5HBHS1M","slack-gif-creator","Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FSKILL.md",[219,222],{"categoryNo":220,"categoryName":221,"taxonomyType":85,"taxonomyTypeDesc":86},"01JBSEEDCAT000000000000005","邮件与沟通",{"categoryNo":223,"categoryName":224,"taxonomyType":85,"taxonomyTypeDesc":86},"01JBSEEDCAT000000000000016","图像与多媒体",[226,227,228,175,229,104,230,231,180,32,232,187,233,234,235,111,236,24],"slack gif creator","slack","gif","validation","constraints","Animation","me","make","Utilities","concepts","request"]