apollo-performance-tuning
Optimize Apollo.io API performance. Use when improving API response times, reducing latency, or optimizing bulk operations. Trigger with phrases like "apollo performance", "optimize apollo", "apollo slow", "apollo latency", "speed up apollo".
Install
mkdir -p .claude/skills/apollo-performance-tuning && curl -L -o skill.zip "https://mcp.directory/api/skills/download/5995" && unzip -o skill.zip -d .claude/skills/apollo-performance-tuning && rm skill.zipInstalls to .claude/skills/apollo-performance-tuning
About this skill
Apollo Performance Tuning
Overview
Optimize Apollo.io API performance through response caching, connection pooling, bulk operations, parallel fetching, and result slimming. Key insight: search is free but slow (~500ms), enrichment costs credits — cache aggressively and batch enrichment calls.
Prerequisites
- Valid Apollo API key
- Node.js 18+
Instructions
Step 1: Connection Pooling
Reuse TCP connections to avoid TLS handshake overhead on every request.
// src/apollo/optimized-client.ts
import axios from 'axios';
import https from 'https';
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 10,
maxFreeSockets: 5,
timeout: 30_000,
});
export const optimizedClient = axios.create({
baseURL: 'https://api.apollo.io/api/v1',
headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.APOLLO_API_KEY! },
httpsAgent,
timeout: 15_000,
});
Step 2: Response Caching with Per-Endpoint TTLs
// src/apollo/cache.ts
import { LRUCache } from 'lru-cache';
// Different TTLs based on data volatility
const CACHE_TTLS: Record<string, number> = {
'/organizations/enrich': 24 * 60 * 60 * 1000, // 24h — company data rarely changes
'/people/match': 4 * 60 * 60 * 1000, // 4h — contact data changes occasionally
'/mixed_people/api_search': 15 * 60 * 1000, // 15min — search results are dynamic
'/mixed_companies/search': 30 * 60 * 1000, // 30min — company search
'/contact_stages': 60 * 60 * 1000, // 1h — stages rarely change
};
const cache = new LRUCache<string, { data: any; at: number }>({
max: 5000,
maxSize: 50 * 1024 * 1024,
sizeCalculation: (v) => JSON.stringify(v).length,
});
function cacheKey(endpoint: string, params: any): string {
return `${endpoint}:${JSON.stringify(params)}`;
}
export async function cachedRequest<T>(
endpoint: string,
requestFn: () => Promise<T>,
params: any,
): Promise<T> {
const key = cacheKey(endpoint, params);
const ttl = CACHE_TTLS[endpoint] ?? 15 * 60 * 1000;
const cached = cache.get(key);
if (cached && Date.now() - cached.at < ttl) return cached.data;
const data = await requestFn();
cache.set(key, { data, at: Date.now() });
return data;
}
export function getCacheStats() {
return { entries: cache.size, sizeBytes: cache.calculatedSize };
}
Step 3: Use Bulk Endpoints Over Single Calls
Apollo's bulk enrichment endpoint handles 10 records per call vs 1. Massive performance gain.
// src/apollo/bulk-ops.ts
import { optimizedClient } from './optimized-client';
import PQueue from 'p-queue';
const queue = new PQueue({ concurrency: 3, intervalCap: 2, interval: 1000 });
// Enrich 100 people: 100 individual calls = 100 requests @ 500ms = 50s
// Batch of 10: 10 bulk calls @ 600ms = 6s (8x faster, same credits)
export async function batchEnrich(
details: Array<{ email?: string; linkedin_url?: string; first_name?: string; last_name?: string; organization_domain?: string }>,
): Promise<any[]> {
const results: any[] = [];
for (let i = 0; i < details.length; i += 10) {
const batch = details.slice(i, i + 10);
const result = await queue.add(async () => {
const { data } = await optimizedClient.post('/people/bulk_match', {
details: batch,
reveal_personal_emails: false,
reveal_phone_number: false,
});
return data.matches ?? [];
});
results.push(...(result ?? []));
}
return results;
}
Step 4: Parallel Search with Concurrency Control
export async function parallelSearch(
domains: string[],
concurrency: number = 5,
): Promise<Map<string, any[]>> {
const searchQueue = new PQueue({ concurrency });
const results = new Map<string, any[]>();
await searchQueue.addAll(
domains.map((domain) => async () => {
const data = await cachedRequest(
'/mixed_people/api_search',
() => optimizedClient.post('/mixed_people/api_search', {
q_organization_domains_list: [domain],
person_seniorities: ['vp', 'director', 'c_suite'],
per_page: 25,
}).then((r) => r.data),
{ domain },
);
results.set(domain, data.people ?? []);
}),
);
return results;
}
Step 5: Slim Response Payloads
Apollo returns large person objects (~2KB each). Extract only needed fields to reduce memory.
interface SlimPerson {
id: string;
name: string;
title: string;
email?: string;
company: string;
seniority: string;
}
function slimPerson(raw: any): SlimPerson {
return {
id: raw.id,
name: raw.name,
title: raw.title,
email: raw.email,
company: raw.organization?.name ?? '',
seniority: raw.seniority ?? '',
};
}
// Use immediately after API call to free memory
const { data } = await optimizedClient.post('/mixed_people/api_search', { ... });
const slim = data.people.map(slimPerson); // ~200 bytes each instead of ~2KB
Step 6: Benchmark Your Endpoints
async function benchmark() {
const endpoints = [
{ name: 'People Search', fn: () => optimizedClient.post('/mixed_people/api_search',
{ q_organization_domains_list: ['apollo.io'], per_page: 1 }) },
{ name: 'Org Enrich', fn: () => optimizedClient.get('/organizations/enrich',
{ params: { domain: 'apollo.io' } }) },
{ name: 'Auth Health', fn: () => optimizedClient.get('/auth/health') },
];
for (const ep of endpoints) {
const times: number[] = [];
for (let i = 0; i < 5; i++) {
const start = Date.now();
try { await ep.fn(); } catch {}
times.push(Date.now() - start);
}
const avg = Math.round(times.reduce((a, b) => a + b) / times.length);
const p95 = times.sort((a, b) => a - b)[Math.floor(times.length * 0.95)];
console.log(`${ep.name}: avg=${avg}ms, p95=${p95}ms`);
}
}
Output
- Connection pooling with
keepAliveand configurablemaxSockets - LRU cache with per-endpoint TTLs (24h org, 4h contact, 15m search)
- Bulk enrichment via
/people/bulk_match(10x fewer requests) - Parallel search with
p-queueconcurrency control - Response slimming reducing memory from ~2KB to ~200B per person
- Benchmarking script measuring avg and p95 latency
Error Handling
| Issue | Resolution |
|---|---|
| High latency | Enable connection pooling, check for stale cache |
| Cache misses | Increase TTL for stable data (org enrichment) |
| Rate limits with parallelism | Reduce p-queue concurrency |
| Memory growth | Lower LRU max entries, slim response payloads |
Resources
Next Steps
Proceed to apollo-cost-tuning for cost optimization.
More by jeremylongshore
View all skills by jeremylongshore →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
Related MCP Servers
Browse all serversOptimize Facebook ad campaigns with AI-driven insights, creative analysis, and campaign control in Meta Ads Manager for
Use Google Lighthouse to check web page performance and optimize website speed. Try our landing page optimizer for bette
V-Rapper lets you instantly access Evan You's VueConf 2025 rap video on Bilibili—get the video URL in one simple query.
Ignission — TikTok analytics and content strategy tools to grow engagement, optimize posts, and track performance with a
Scorecard: Evaluate and optimize LLM systems with thorough testing, actionable metrics, and performance insights to impr
CatchMetrics — Real User Monitoring for web performance analytics and Core Web Vitals tracking. Optimize UX, fix regress
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.