klaviyo-performance-tuning

Optimize Klaviyo API performance with caching, batching, and pagination tuning. Use when experiencing slow API responses, implementing caching strategies, or optimizing request throughput for Klaviyo integrations. Trigger with phrases like "klaviyo performance", "optimize klaviyo", "klaviyo latency", "klaviyo caching", "klaviyo slow", "klaviyo batch".

1,868 stars

Best use case

klaviyo-performance-tuning is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Optimize Klaviyo API performance with caching, batching, and pagination tuning. Use when experiencing slow API responses, implementing caching strategies, or optimizing request throughput for Klaviyo integrations. Trigger with phrases like "klaviyo performance", "optimize klaviyo", "klaviyo latency", "klaviyo caching", "klaviyo slow", "klaviyo batch".

Teams using klaviyo-performance-tuning should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/klaviyo-performance-tuning/SKILL.md --create-dirs "https://raw.githubusercontent.com/jeremylongshore/claude-code-plugins-plus-skills/main/plugins/saas-packs/klaviyo-pack/skills/klaviyo-performance-tuning/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/klaviyo-performance-tuning/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How klaviyo-performance-tuning Compares

Feature / Agentklaviyo-performance-tuningStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Optimize Klaviyo API performance with caching, batching, and pagination tuning. Use when experiencing slow API responses, implementing caching strategies, or optimizing request throughput for Klaviyo integrations. Trigger with phrases like "klaviyo performance", "optimize klaviyo", "klaviyo latency", "klaviyo caching", "klaviyo slow", "klaviyo batch".

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Klaviyo Performance Tuning

## Overview

Optimize Klaviyo API performance with response caching, request batching, cursor-based pagination, sparse fieldsets, and connection pooling.

## Prerequisites

- `klaviyo-api` SDK installed
- Understanding of Klaviyo's rate limits (75 req/s burst, 700 req/min)
- Redis or in-memory cache (optional)

## Klaviyo API Performance Characteristics

| Operation | Typical Latency | Max Page Size |
|-----------|----------------|---------------|
| Get Profile by ID | 50-150ms | N/A |
| Get Profiles (list) | 100-300ms | 20 (default), 100 (some endpoints) |
| Create Profile | 100-200ms | N/A |
| Create Event | 50-100ms | N/A |
| Get Segment Profiles | 200-500ms | 20 |
| Campaign Operations | 200-500ms | 20 |

## Instructions

### Step 1: Sparse Fieldsets (Reduce Payload Size)

Klaviyo supports JSON:API sparse fieldsets -- request only the fields you need.

```typescript
// BAD: Fetches all profile fields (20+ attributes)
const profiles = await profilesApi.getProfiles();

// GOOD: Only fetch email and firstName (much smaller payload)
const profiles = await profilesApi.getProfiles({
  fieldsProfile: ['email', 'first_name', 'created'],
});
// Note: fieldsProfile uses snake_case field names (API-level names)

// Fetch profiles with included list relationships
const profilesWithLists = await profilesApi.getProfiles({
  fieldsProfile: ['email', 'first_name'],
  include: ['lists'],
  fieldsLists: ['name'],
});
```

### Step 2: Response Caching

```typescript
// src/klaviyo/cache.ts
import { LRUCache } from 'lru-cache';

const cache = new LRUCache<string, any>({
  max: 5000,             // Max cached items
  ttl: 60 * 1000,        // 1 minute default TTL
  updateAgeOnGet: true,   // Reset TTL on access
});

export async function cachedKlaviyoCall<T>(
  key: string,
  fetcher: () => Promise<T>,
  ttlMs?: number
): Promise<T> {
  const cached = cache.get(key);
  if (cached !== undefined) return cached as T;

  const result = await fetcher();
  cache.set(key, result, { ttl: ttlMs });
  return result;
}

// Cache profile lookups by email
export async function getCachedProfile(email: string) {
  return cachedKlaviyoCall(
    `profile:${email}`,
    () => profilesApi.getProfiles({ filter: `equals(email,"${email}")` }),
    5 * 60 * 1000  // 5 minute TTL for profiles
  );
}

// Cache segment data (changes less frequently)
export async function getCachedSegments() {
  return cachedKlaviyoCall(
    'segments:all',
    () => segmentsApi.getSegments(),
    15 * 60 * 1000  // 15 minute TTL for segments
  );
}
```

### Step 3: Efficient Pagination

```typescript
// src/klaviyo/pagination.ts

/**
 * Auto-paginate with configurable page size and concurrency.
 * Klaviyo cursor pagination: response.body.links.next contains the cursor URL.
 */
export async function fetchAllPages<T>(
  fetcher: (pageCursor?: string) => Promise<{
    body: { data: T[]; links?: { next?: string } };
  }>,
  options = { maxPages: 100 }
): Promise<T[]> {
  const results: T[] = [];
  let cursor: string | undefined;
  let pageCount = 0;

  do {
    const response = await fetcher(cursor);
    results.push(...response.body.data);
    pageCount++;

    const nextLink = response.body.links?.next;
    if (nextLink && pageCount < options.maxPages) {
      const url = new URL(nextLink);
      cursor = url.searchParams.get('page[cursor]') || undefined;
    } else {
      cursor = undefined;
    }
  } while (cursor);

  return results;
}

// Usage: fetch all profiles in a list
const allProfiles = await fetchAllPages(
  (cursor) => listsApi.getListProfiles({ id: listId, pageCursor: cursor })
);
console.log(`Total profiles: ${allProfiles.length}`);
```

### Step 4: Request Batching with DataLoader

```typescript
import DataLoader from 'dataloader';
import { ProfilesApi } from 'klaviyo-api';

// Batch profile lookups: multiple getProfile(id) calls within
// a single tick are combined into one getProfiles() call
const profileLoader = new DataLoader<string, any>(
  async (profileIds) => {
    // Klaviyo doesn't have a batch-get-by-IDs endpoint,
    // so we fetch individually but with concurrency control
    const results = await Promise.allSettled(
      profileIds.map(id => profilesApi.getProfile({ id }))
    );
    return results.map(r =>
      r.status === 'fulfilled' ? r.value.body.data : null
    );
  },
  {
    maxBatchSize: 10,  // Stay well under rate limits
    batchScheduleFn: cb => setTimeout(cb, 50),  // 50ms batch window
    cache: true,  // In-memory cache within the DataLoader
  }
);

// These three calls are batched into concurrent requests
const [p1, p2, p3] = await Promise.all([
  profileLoader.load('PROFILE_ID_1'),
  profileLoader.load('PROFILE_ID_2'),
  profileLoader.load('PROFILE_ID_3'),
]);
```

### Step 5: Parallel API Calls with Concurrency Control

```typescript
import PQueue from 'p-queue';

// Process large operations with controlled concurrency
const queue = new PQueue({
  concurrency: 10,    // Max 10 parallel requests
  interval: 1000,     // Per second
  intervalCap: 50,    // 50 requests/second (safe margin under 75 burst)
});

// Example: update 10,000 profiles efficiently
async function bulkUpdateProfiles(updates: Array<{ email: string; data: any }>) {
  let completed = 0;

  const promises = updates.map(update =>
    queue.add(async () => {
      await profilesApi.createOrUpdateProfile({
        data: {
          type: 'profile' as any,
          attributes: { email: update.email, ...update.data },
        },
      });
      completed++;
      if (completed % 500 === 0) {
        console.log(`Progress: ${completed}/${updates.length}`);
      }
    })
  );

  await Promise.allSettled(promises);
  console.log(`Done: ${completed}/${updates.length}`);
}
```

### Step 6: Performance Monitoring

```typescript
// src/klaviyo/perf-monitor.ts

interface PerfMetrics {
  operation: string;
  durationMs: number;
  success: boolean;
  cached: boolean;
}

const perfLog: PerfMetrics[] = [];

export async function measuredCall<T>(
  operation: string,
  fn: () => Promise<T>,
  cached = false
): Promise<T> {
  const start = performance.now();
  try {
    const result = await fn();
    perfLog.push({ operation, durationMs: performance.now() - start, success: true, cached });
    return result;
  } catch (error) {
    perfLog.push({ operation, durationMs: performance.now() - start, success: false, cached });
    throw error;
  }
}

export function getPerfSummary(): Record<string, { avg: number; p95: number; count: number }> {
  const byOp: Record<string, number[]> = {};
  for (const m of perfLog) {
    (byOp[m.operation] ??= []).push(m.durationMs);
  }
  const summary: Record<string, any> = {};
  for (const [op, durations] of Object.entries(byOp)) {
    durations.sort((a, b) => a - b);
    summary[op] = {
      avg: Math.round(durations.reduce((a, b) => a + b, 0) / durations.length),
      p95: Math.round(durations[Math.floor(durations.length * 0.95)]),
      count: durations.length,
    };
  }
  return summary;
}
```

## Error Handling

| Issue | Cause | Solution |
|-------|-------|----------|
| Cache stampede | Many requests on cache miss | Use stale-while-revalidate pattern |
| Pagination timeout | Very large datasets | Set `maxPages` limit, process in chunks |
| Rate limit on bulk ops | Too much concurrency | Reduce `PQueue` concurrency/intervalCap |
| Slow filter queries | Complex filter expressions | Simplify filters, use segment IDs instead |

## Resources

- [Klaviyo API Filtering](https://developers.klaviyo.com/en/reference/api_overview#filtering)
- [JSON:API Sparse Fieldsets](https://jsonapi.org/format/#fetching-sparse-fieldsets)
- [DataLoader](https://github.com/graphql/dataloader)
- [p-queue](https://github.com/sindresorhus/p-queue)

## Next Steps

For cost optimization, see `klaviyo-cost-tuning`.

Related Skills

running-performance-tests

1868
from jeremylongshore/claude-code-plugins-plus-skills

Execute load testing, stress testing, and performance benchmarking. Use when performing specialized testing. Trigger with phrases like "run load tests", "test performance", or "benchmark the system".

workhuman-performance-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Workhuman performance tuning for employee recognition and rewards API. Use when integrating Workhuman Social Recognition, or building recognition workflows with HRIS systems. Trigger: "workhuman performance tuning".

workhuman-cost-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Workhuman cost tuning for employee recognition and rewards API. Use when integrating Workhuman Social Recognition, or building recognition workflows with HRIS systems. Trigger: "workhuman cost tuning".

wispr-performance-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Wispr Flow performance tuning for voice-to-text API integration. Use when integrating Wispr Flow dictation, WebSocket streaming, or building voice-powered applications. Trigger: "wispr performance tuning".

wispr-cost-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Wispr Flow cost tuning for voice-to-text API integration. Use when integrating Wispr Flow dictation, WebSocket streaming, or building voice-powered applications. Trigger: "wispr cost tuning".

windsurf-performance-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Optimize Windsurf IDE performance: indexing speed, Cascade responsiveness, and memory usage. Use when Windsurf is slow, indexing takes too long, Cascade times out, or the IDE uses too much memory. Trigger with phrases like "windsurf slow", "windsurf performance", "optimize windsurf", "windsurf memory", "cascade slow", "indexing slow".

windsurf-cost-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Optimize Windsurf licensing costs through seat management, tier selection, and credit monitoring. Use when analyzing Windsurf billing, reducing per-seat costs, or implementing usage monitoring and budget controls. Trigger with phrases like "windsurf cost", "windsurf billing", "reduce windsurf costs", "windsurf pricing", "windsurf budget".

webflow-performance-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Optimize Webflow API performance with response caching, bulk endpoint batching, CDN-cached live item reads, pagination optimization, and connection pooling. Use when experiencing slow API responses or optimizing request throughput. Trigger with phrases like "webflow performance", "optimize webflow", "webflow latency", "webflow caching", "webflow slow", "webflow batch".

webflow-cost-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Optimize Webflow costs through plan selection, CDN read optimization, bulk endpoint usage, and API usage monitoring with budget alerts. Use when analyzing Webflow billing, reducing API costs, or implementing usage monitoring for Webflow integrations. Trigger with phrases like "webflow cost", "webflow billing", "reduce webflow costs", "webflow pricing", "webflow budget".

vercel-performance-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Optimize Vercel deployment performance with caching, bundle optimization, and cold start reduction. Use when experiencing slow page loads, optimizing Core Web Vitals, or reducing serverless function cold start times. Trigger with phrases like "vercel performance", "optimize vercel", "vercel latency", "vercel caching", "vercel slow", "vercel cold start".

vercel-cost-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Optimize Vercel costs through plan selection, function efficiency, and usage monitoring. Use when analyzing Vercel billing, reducing function execution costs, or implementing spend management and budget alerts. Trigger with phrases like "vercel cost", "vercel billing", "reduce vercel costs", "vercel pricing", "vercel expensive", "vercel budget".

veeva-performance-tuning

1868
from jeremylongshore/claude-code-plugins-plus-skills

Veeva Vault performance tuning for REST API and clinical operations. Use when working with Veeva Vault document management and CRM. Trigger: "veeva performance tuning".