Skip to main content
navan-performance-tuning Use when optimizing Navan API call patterns for high-volume integrations — caching, batching, connection pooling, and pagination strategies.
Trigger with "navan performance tuning" or "navan api optimization" or "navan caching".
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill navan-performance-tuning명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... 이 저장소의 다른 Skills Implement user sign-up and sign-in flows with Clerk.
Use when building authentication UI, customizing sign-in experience,
or implementing OAuth social login.
Trigger with phrases like "clerk sign-in", "clerk sign-up",
"clerk login flow", "clerk OAuth", "clerk social login".
Implement session management and middleware with Clerk.
Use when managing user sessions, configuring route protection,
or implementing token refresh and custom JWT templates.
Trigger with phrases like "clerk session", "clerk middleware",
"clerk route protection", "clerk token", "clerk JWT".
Configure enterprise SSO, role-based access control, and organization management.
Use when implementing SSO integration, configuring role-based permissions,
or setting up organization-level controls.
Trigger with phrases like "clerk SSO", "clerk RBAC",
"clerk enterprise", "clerk roles", "clerk permissions", "clerk organizations".
jeremylongshore
jeremylongshore/claude-code-plugins-plus-skills
GitHub 저장소 열기 name navan-performance-tuning description Use when optimizing Navan API call patterns for high-volume integrations — caching, batching, connection pooling, and pagination strategies.
Trigger with "navan performance tuning" or "navan api optimization" or "navan caching".
allowed-tools Read, Write, Edit, Bash(curl:*), Grep, Glob version 1.7.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","navan","travel"] compatibility Designed for Claude Code
Navan Performance Tuning
Overview Navan's REST API has no bulk endpoints or GraphQL — every data fetch is a separate HTTP request. High-volume integrations syncing thousands of bookings, expenses, or user records quickly become bottlenecked by sequential API calls, redundant fetches, and naive pagination. This skill provides concrete optimization patterns: response caching with data-type-specific TTLs, parallel request execution with concurrency controls, cursor-based pagination handling, and HTTP connection reuse. Each pattern targets the real constraint: minimizing total API calls while staying under rate limits.
Prerequisites
Active Navan integration with OAuth 2.0 credentials (client_credentials grant)
Node.js 18+ (for native fetch and AbortController)
Understanding of your data volume — bookings/day, users, expense reports/month
API base URL: https://api.navan.com/v1
Instructions
Step 1 — Implement Response Caching with Data-Appropriate TTLs Different Navan data types change at different rates. Cache accordingly:
interface CacheEntry <T> {
data : T;
expires_at : number ;
etag ?: string ;
}
const CACHE_TTL : Record <string , number > = {
'users' : 3600_000 ,
'policies' : 86400_000 ,
'bookings' : 300_000 ,
'expenses' : 600_000 ,
};
const cache = new Map <string , CacheEntry <unknown >>();
async function cachedFetch<T>(
endpoint : string ,
token : string
): Promise <T> {
const cacheKey = endpoint;
const entry = cache.get (cacheKey) as CacheEntry <T> | undefined ;
if (entry && entry.expires_at > Date .now ()) {
return entry.data ;
}
const dataType = endpoint.split ('?' )[0 ].split ('/' )[0 ];
const ttl = CACHE_TTL [dataType] ?? 300_000 ;
const response = await fetch (`https://api.navan.com/v1/${endpoint} ` , {
headers : {
'Authorization' : `Bearer ${token} ` ,
'Content-Type' : 'application/json' ,
},
});
if (!response.ok ) {
throw new Error (`Navan API ${response.status} : ${endpoint} ` );
}
const data = await response.json () as T;
cache.set (cacheKey, {
data,
expires_at : Date .now () + ttl,
etag : response.headers .get ('etag' ) ?? undefined ,
});
return data;
}
Step 2 — Parallel Fetch with Concurrency Throttling Fetch multiple resources concurrently without overwhelming rate limits:
async function parallelFetch<T>(
endpoints : string [],
token : string ,
concurrency : number = 5
): Promise <T[]> {
const results : T[] = [];
const queue = [...endpoints];
async function worker ( ): Promise <void > {
while (queue.length > 0 ) {
const endpoint = queue.shift ()!;
try {
const data = await cachedFetch<T>(endpoint, token);
results.push (data);
} catch (err) {
const status = (err as Error ).message .match (/(\d{3})/ )?.[1 ];
if (status === '429' ) {
queue.unshift (endpoint);
await new Promise (r => setTimeout (r, 2000 ));
} else {
throw err;
}
}
}
}
const workers = Array .from (
{ length : Math .min (concurrency, endpoints.length ) },
() => worker ()
);
await Promise .all (workers);
return results;
}
const userIds = ['u_001' , 'u_002' , 'u_020' ];
const profiles = await parallelFetch (
userIds.map (id => `users/${id} ` ),
token,
5
);
Step 3 — Efficient Cursor-Based Pagination Page through large result sets without missing or duplicating records:
async function * paginateAll<T>(
endpoint : string ,
token : string ,
pageSize : number = 50
): AsyncGenerator <T[]> {
let page = 0 ;
while (true ) {
const params = new URLSearchParams ({
page : String (page),
size : String (pageSize),
});
const url = `https://api.navan.com/v1/${endpoint} ?${params} ` ;
const response = await fetch (url, {
headers : { 'Authorization' : `Bearer ${token} ` },
});
if (!response.ok ) {
throw new Error (`Navan API ${response.status} on ${endpoint} ` );
}
const body = await response.json ();
const items : T[] = body.data ?? [];
if (items.length === 0 ) break ;
yield items;
if (items.length < pageSize) break ;
page++;
}
}
let totalProcessed = 0 ;
for await (const page of paginateAll ('bookings' , token, 50 )) {
await processBatch (page);
totalProcessed += page.length ;
console .log (`Processed ${totalProcessed} bookings` );
}
Step 4 — HTTP Connection Reuse Keep TCP connections alive across multiple API calls:
import { Agent } from 'undici' ;
const navanAgent = new Agent ({
keepAliveTimeout : 30_000 ,
keepAliveMaxTimeout : 60_000 ,
connections : 10 ,
pipelining : 1 ,
});
const response = await fetch ('https://api.navan.com/v1/bookings' , {
headers : { 'Authorization' : `Bearer ${token} ` },
dispatcher : navanAgent,
});
Output Optimized Navan API integration with:
60-80% fewer API calls through intelligent caching
5-10x faster sync jobs via parallel execution
Zero missed records with robust cursor pagination
Lower latency from connection reuse and keep-alive
Error Handling HTTP Code Meaning Performance Action 200Success Cache the response with appropriate TTL 304Not Modified Use cached version (ETag match) 401Token expired Refresh token, retry once, do not cache 429Rate limited Exponential backoff: 1s, 2s, 4s — max 3 retries 500Server error Retry once after 5s, skip on second failure 503Service unavailable Pause all workers for 30s, then resume
Examples Before and after optimization for a 10,000-booking sync:
Before (naive sequential):
API calls: 10,000 (one per booking)
Time: 45 minutes
Rate limit hits: 12
After (cached + parallel + paginated):
API calls: 200 (pages of 50)
Time: 4 minutes
Rate limit hits: 0
Cache invalidation on webhook event:
function handleWebhook (event : { type : string ; booking_id: string } ) {
if (event.type === 'booking.updated' ) {
cache.delete (`bookings/${event.booking_id} ` );
}
}
Resources
Next Steps
Add navan-rate-limits for detailed rate limit handling strategies
Add navan-cost-tuning to optimize the business cost side alongside API performance
See navan-observability to measure the impact of these optimizations