本文へ移動
cccskills
無料GitHub で公開

appfolio-cost-tuning

Optimize AppFolio API costs through efficient usage patterns. Trigger: "appfolio cost".

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.3 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

AppFolio Cost Tuning

Overview

AppFolio Stack API pricing is partner-agreement based, with costs scaling by API call volume per managed property. Property management portfolios generate high-frequency reads for tenant lookups, lease status checks, and maintenance requests. Each redundant API call erodes margin on per-unit revenue. Optimizing call patterns directly impacts operational profitability, especially for portfolios managing hundreds or thousands of units where even small per-call costs compound rapidly.

Prerequisites

  • The current partner agreement’s actual billing, endpoint quota, export, and event-delivery terms; treat published examples as planning inputs, not price commitments.
  • A data classification and retention policy that prevents tenant, lease, and financial payloads from being retained in generic process memory or caches.
  • Per-endpoint call budgets, cache owners, and a reconciliation path for stale reads that could affect accounting, lease, or maintenance decisions.

Instructions

  1. Measure the existing call rate, cache hit rate, payload sizes, and provider charges by endpoint before changing a TTL or polling interval.
  2. Cache only the minimized, non-sensitive fields required by the caller, with a bounded size and an endpoint-specific freshness policy.
  3. Use incremental reads or provider-supported events only after verifying the partner capability and loss/replay semantics; otherwise use bounded polling.
  4. Stop or degrade non-critical work at the approved budget threshold and send stale or incomplete financial/lease data to an operator rather than guessing.

Cost Breakdown

ComponentCost DriverOptimization
Property/unit readsPer-call pricing on tenant and unit endpointsCache with 10-15 min TTL; property data changes infrequently
Lease operationsBulk lease queries across entire portfolioFetch all leases once, filter locally instead of per-unit calls
Maintenance requestsPolling for new work ordersUse verified provider events, or bounded incremental polling
Reporting exportsLarge payload downloads for financial reportsSchedule off-peak, cache results for 24h
Vendor/owner lookupsRepeated lookups for the same contactsBuild a local lookup table, refresh daily

API Call Reduction

class AppFolioCache {
  private cache = new Map<string, { data: unknown; expiry: number }>();
  private readonly maxEntries = 1_000;

  get(key: string): any | null {
    const entry = this.cache.get(key);
    if (!entry || Date.now() > entry.expiry) return null;
    return entry.data;
  }

  set(key: string, data: unknown, ttlMs = 600_000): void {
    if (this.cache.size >= this.maxEntries && !this.cache.has(key)) {
      this.cache.delete(this.cache.keys().next().value!);
    }
    this.cache.set(key, { data, expiry: Date.now() + ttlMs });
  }

  async fetchWithCache(endpoint: string, ttlMs?: number): Promise<any> {
    const cached = this.get(endpoint);
    if (cached) return cached;
    const response = await fetch(endpoint);
    const data = await response.json();
    this.set(endpoint, data, ttlMs);
    return data;
  }
}

Usage Monitoring

class AppFolioUsageMonitor {
  private calls: Array<{ endpoint: string; timestamp: number }> = [];
  private budgetLimit = 10_000; // daily call budget

  record(endpoint: string): void {
    this.calls.push({ endpoint, timestamp: Date.now() });
    const todayCalls = this.getTodayCount();
    if (todayCalls > this.budgetLimit * 0.8) {
      console.warn(`AppFolio API budget 80% consumed: ${todayCalls}/${this.budgetLimit}`);
    }
  }

  getTodayCount(): number {
    const startOfDay = new Date().setHours(0, 0, 0, 0);
    return this.calls.filter(c => c.timestamp > startOfDay).length;
  }
}

Cost Optimization Checklist

  • Cache property and unit data with 10-15 min TTL
  • Replace polling loops with verified event delivery or bounded incremental polling
  • Batch lease queries — fetch all, filter locally
  • Use incremental sync with modified_since parameter
  • Schedule report exports during off-peak hours
  • Build local lookup tables for vendors and owners
  • Set daily API call budget alerts at 80% threshold
  • Audit unused integrations consuming API quota

Error Handling

IssueCauseFix
429 Too Many RequestsExceeded rate limitImplement exponential backoff with jitter
Stale cache serving old dataTTL too long for volatile dataReduce TTL for maintenance/lease endpoints to 2-5 min
Budget alerts firing dailyPolling loop running on short intervalSwitch to webhook-driven architecture
Duplicate API callsMultiple services fetching same dataCentralize through shared cache layer
Large payload timeoutsFetching full portfolio in single callPaginate requests, process in batches of 100

Output

  • A measured per-endpoint call and cache budget with an accountable owner
  • A bounded, minimized cache policy and a clear stale-data decision boundary
  • A documented decision to pause, defer, or reconcile work when the budget, provider capability, or data freshness requirement cannot be met

Examples

For a nightly property-status sync, capture a baseline call count and response size, cache only the property ID and permitted occupancy summary, and cap the cache at the approved entry count. Enable an incremental cursor only after a staging replay proves no records are lost; otherwise retain low-frequency, rate-limited polling. When the budget alert fires, stop non-critical refreshes and surface the age of the last verified result. Do not use cached or partial data to make a lease, payment, or safety decision without operator review.

Resources

Next Steps

See appfolio-performance-tuning.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Build a synthetic-data CI gate for customer-controlled Abridge integration code without calling undocumented vendor interfaces. Use when adding regression checks to an Abridge deployment repository. Trigger with "test the Abridge integration".

日本語の概要は準備中です。原文の説明を表示しています。

jeremylongshore/tons-of-skills-marketplace2,8322026年10月13日 更新

Triage Abridge recording, note-review, Epic handoff, and access failures from observed evidence without inventing vendor error codes. Use when an Abridge clinical workflow is degraded. Trigger with "diagnose this Abridge issue".

日本語の概要は準備中です。原文の説明を表示しています。

jeremylongshore/tons-of-skills-marketplace2,8322026年10月13日 更新

Design and verify the clinician workflow from consent through recording, draft review, Linked Evidence, and final note disposition. Use when implementing or auditing an Abridge clinical documentation pathway. Trigger with "map the Abridge note workflow".

日本語の概要は準備中です。原文の説明を表示しています。

jeremylongshore/tons-of-skills-marketplace2,8322026年10月13日 更新

Verify the approved handoff of clinician-reviewed Abridge note sections into Epic templates and downstream workflows. Use when configuring or auditing Abridge-to-Epic documentation flow. Trigger with "verify the Abridge Epic handoff".

日本語の概要は準備中です。原文の説明を表示しています。

jeremylongshore/tons-of-skills-marketplace2,8322026年10月13日 更新

Evaluate Abridge adoption, workflow value, and avoidable operational friction without inventing prices or vendor billing meters. Use when reviewing an Abridge rollout or renewal. Trigger with "analyze Abridge value".

日本語の概要は準備中です。原文の説明を表示しています。

jeremylongshore/tons-of-skills-marketplace2,8322026年10月13日 更新

Produce a PHI-minimized Abridge support bundle with provenance, redaction, and protected escalation boundaries. Use when support needs reproducible evidence for an Abridge issue. Trigger with "build an Abridge debug bundle".

日本語の概要は準備中です。原文の説明を表示しています。

jeremylongshore/tons-of-skills-marketplace2,8322026年10月13日 更新

jeremylongshore のスキルをすべて見る

このスキルの問題を報告する