Figma Performance Tuning
SkillMedia'Optimize Figma REST API performance with caching, partial fetches, and
Use Figma Performance Tuning in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add Figma Performance Tuning and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the Figma Performance Tuning skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by jeremylongshore/tons-of-skills-marketplace in skills/.curated/figma-performance-tuning/SKILL.md and read by ahel’s review.
Overview
Optimize Figma REST API performance. Large Figma files can return multi-megabyte JSON responses. Key strategies: fetch only what you need, cache aggressively, and batch requests.
Prerequisites
- Working Figma API integration
- Understanding of your access patterns (which endpoints, how often)
Instructions
Step 1: Reduce Payload Size
// BAD: fetches the entire file tree (can be 10+ MB for large files)
const file = await fetch(`https://api.figma.com/v1/files/${fileKey}`, {
headers: { 'X-Figma-Token': token },
}).then(r => r.json());
// GOOD: use depth parameter to limit tree depth
// depth=1 returns only pages (CANVAS nodes), not their children
const fileMeta = await fetch(
`https://api.figma.com/v1/files/${fileKey}?depth=1`,
{ headers: { 'X-Figma-Token': token } }
).then(r => r.json());
// GOOD: fetch only specific nodes you need
const nodes = await fetch(
`https://api.figma.com/v1/files/${fileKey}/nodes?ids=${nodeIds.join(',')}`,
{ headers: { 'X-Figma-Token': token } }
).then(r => r.json());
// GOOD: use plugin_data or branch_data params only when needed
// By default, plugin data and branch data are NOT returned
Step 2: Response Caching
import { LRUCache } from 'lru-cache';
// File metadata changes rarely -- cache for 5 minutes
const fileCache = new LRUCache<string, any>({
max: 100,
ttl: 5 * 60 * 1000, // 5 minutes
});
async function getCachedFile(fileKey: string, token: string) {
const cached = fileCache.get(fileKey);
if (cached) return cached;
const file = await fetch(
`https://api.figma.com/v1/files/${fileKey}?depth=1`,
{ headers: { 'X-Figma-Token': token } }
).then(r => r.json());
fileCache.set(fileKey, file);
return file;
}
// Image URLs expire after 30 days -- cache them but with a shorter TTL
const imageUrlCache = new LRUCache<string, string>({
max: 1000,
ttl: 24 * 60 * 60 * 1000, // 1 day (well within 30-day expiry)
});
async function getCachedImageUrl(
fileKey: string, nodeId: string, format: string, token: string
): Promise<string | null> {
const cacheKey = `${fileKey}:${nodeId}:${format}`;
const cached = imageUrlCache.get(cacheKey);
if (cached) return cached;
const data = await fetch(
`https://api.figma.com/v1/images/${fileKey}?ids=${nodeId}&format=${format}`,
{ headers: { 'X-Figma-Token': token } }
).then(r => r.json());
const url = data.images[nodeId];
if (url) imageUrlCache.set(cacheKey, url);
return url;
}
Step 3: Webhook-Driven Cache Invalidation
// Instead of polling, use webhooks to know when to re-fetch
// See figma-webhooks-events for full webhook setup
async function handleFileUpdate(fileKey: string) {
// Invalidate cached data for this file
fileCache.delete(fileKey);
// Proactively re-fetch commonly accessed data
const token = process.env.FIGMA_PAT!;
await getCachedFile(fileKey, token);
console.log(`Cache invalidated and refreshed for ${fileKey}`);
}
Step 4: Batch Node Fetches
// The /nodes endpoint accepts multiple IDs -- batch them
// Max practical batch size: ~50-100 IDs per request
async function batchFetchNodes(
fileKey: string,
nodeIds: string[],
token: string,
batchSize = 50
): Promise<Map<string, any>> {
const results = new Map<string, any>();
for (let i = 0; i < nodeIds.length; i += batchSize) {
const batch = nodeIds.slice(i, i + batchSize);
const ids = encodeURIComponent(batch.join(','));
const data = await fetch(
`https://api.figma.com/v1/files/${fileKey}/nodes?ids=${ids}`,
{ headers: { 'X-Figma-Token': token } }
).then(r => r.json());
for (const [id, node] of Object.entries(data.nodes)) {
results.set(id, node);
}
}
return results;
}
Step 5: Connection Reuse
import { Agent } from 'undici';
// Reuse HTTP connections to api.figma.com
const figmaAgent = new Agent({
keepAliveTimeout: 30_000,
keepAliveMaxTimeout: 60_000,
connections: 5,
});
// Use with Node.js 18+ built-in fetch
async function optimizedFetch(path: string, token: string) {
return fetch(`https://api.figma.com${path}`, {
headers: { 'X-Figma-Token': token },
// @ts-ignore -- dispatcher is a Node.js fetch option
dispatcher: figmaAgent,
});
}
Output
- Reduced API payload sizes with
depthandnodesendpoints - Response caching with appropriate TTLs
- Webhook-driven cache invalidation
- Batched node fetches reducing request count
- Connection reuse for lower latency
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Stale cache | No invalidation | Use webhooks to invalidate on changes |
| Out of memory | Caching full file JSON | Use depth=1 or nodes endpoint |
| Slow image exports | Large batch, high scale | Reduce scale; batch in groups of 50 |
| Expired image URLs | Cached URL older than 30 days | Set image cache TTL to <24h |
Examples
Measure the win from payload reduction (Step 1) on a real design-system file:
for url in "files/${FIGMA_FILE_KEY}" "files/${FIGMA_FILE_KEY}?depth=1"; do
curl -s -o /dev/null -w "%{size_download}B %{time_total}s ${url}\n" \
-H "X-Figma-Token: ${FIGMA_PAT}" "https://api.figma.com/v1/${url}"
done
41520883B 6.180s files/AbC123 ← full tree
38412B 0.310s files/AbC123?depth=1 ← 1000x smaller, 20x faster
Confirm the version-keyed cache (Step 2) short-circuits repeat fetches:
GET file AbC123 cache MISS (version 1234567890) → fetched, cached
GET file AbC123 cache HIT (version unchanged) → 0 API calls
webhook FILE_UPDATE AbC123 → invalidated → next GET refetches
Batching and connection reuse details: references/batch-node-fetches.md, references/connection-reuse.md.
Resources
Next Steps
For cost optimization, see figma-cost-tuning.
Signals
- GitHub stars
- 3k
- Forks
- 415
- Last commit
- Oct 2026
ahel review
S4info
community integration, published by jeremylongshore, not figmaK2info
exfiltrationK2info
exfiltration (in references/reduce-payload-size.md)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Item type
- skill
- Key
figma-performance-tuning- Source
- github.com/jeremylongshore/tons-of-skills-marketplace
github.com/jeremylongshore/tons-of-skills-marketplace
Related picks
Skill · thedaviddias
The pick for JavaScriptmodern-javascript-patterns
Skill · wshobson
The pick for JavaScriptsetup-ts-deep-modules
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScriptfigma
Skill · heygen-com
The pick for Figmanodejs-backend-patterns
Skill · wshobson
The pick for Node