Optimize Perplexity API performance with caching, batching, and connection pooling.
Use when experiencing slow API responses, implementing caching strategies,
or optimizing request throughput for Perplexity integrations.
Trigger with phrases like "perplexity performance", "optimize perplexity",
"perplexity latency", "perplexity caching", "perplexity slow", "perplexity batch".
Optimize Perplexity Sonar API for latency, throughput, and cost. Key insight: every Perplexity call performs a live web search, so response times are inherently variable. Typical latencies: sonar 1-3s, sonar-pro 3-8s, sonar-deep-research 10-60s.
Latency Benchmarks
Model
Typical Latency
Max Tokens
Best For
sonar
1-3s
4096
Quick answers, simple facts
sonar-pro
3-8s
8192
Deep research, many citations
sonar-reasoning-pro
5-15s
8192
Multi-step analysis
sonar-deep-research
10-60s
8192
Comprehensive reports
Prerequisites
Perplexity API key configured
Understanding of search-augmented generation latency patterns
Cache infrastructure (Redis or in-memory LRU)
Instructions
Step 1: Smart Model Routing
import OpenAI from "openai";
const perplexity = new OpenAI({
apiKey: process.env.PERPLEXITY_API_KEY,
baseURL: "https://api.perplexity.ai",
});
type QueryComplexity = "simple" | "standard" | "deep";
function classifyQuery(query: string): QueryComplexity {
const words = query.split(/\s+/).length;
const simplePatterns = [/^what is/i, /^who is/i, /^when did/i, /^define/i, /^how many/i];
const deepPatterns = [/compare.*vs/i, /analysis of/i, /comprehensive/i, /pros and cons/i, /in-depth/i];
if (simplePatterns.some((p) => p.test(query)) && words < 15) return "simple";
if (deepPatterns.some((p) => p.test(query)) || words > 30) return "deep";
return "standard";
}
function selectModel(complexity: QueryComplexity): { model: string; maxTokens: number } {
switch (complexity) {
case "simple": return { model: "sonar", maxTokens: 256 };
case "standard": return { model: "sonar", maxTokens: 1024 };
case "deep": return { model: "sonar-pro", maxTokens: 4096 };
}
}
async function smartSearch(query: string) {
const complexity = classifyQuery(query);
const { model, maxTokens } = selectModel(complexity);
return perplexity.chat.completions.create({
model,
messages: [{ role: "user", content: query }],
max_tokens: maxTokens,
});
}
Step 2: Query Hash Caching
import { LRUCache } from "lru-cache";
import { createHash } from "crypto";
const CACHE_TTL = {
news: 30 * 60 * 1000, // 30 min for current events
research: 4 * 60 * 60 * 1000, // 4 hours for research
factual: 24 * 60 * 60 * 1000, // 24 hours for stable facts
};
const searchCache = new LRUCache<string, any>({
max: 1000,
ttl: CACHE_TTL.research, // default TTL
});
function cacheKey(query: string, model: string): string {
return createHash("sha256")
.update(`${model}:${query.toLowerCase().trim()}`)
.digest("hex");
}
function detectTTL(query: string): number {
if (/\b(latest|today|breaking|current price|this week)\b/i.test(query))
return CACHE_TTL.news;
if (/\b(what is|define|how does|who is)\b/i.test(query))
return CACHE_TTL.factual;
return CACHE_TTL.research;
}
async function cachedSearch(query: string, model = "sonar") {
const key = cacheKey(query, model);
const cached = searchCache.get(key);
if (cached) return { ...cached, cached: true };
const result = await perplexity.chat.completions.create({
model,
messages: [{ role: "user", content: query }],
});
searchCache.set(key, result, { ttl: detectTTL(query) });
return { ...result, cached: false };
}
Step 3: Streaming for Perceived Performance
async function streamSearch(
query: string,
onChunk: (text: string) => void,
onCitations: (urls: string[]) => void
) {
const stream = await perplexity.chat.completions.create({
model: "sonar-pro",
messages: [{ role: "user", content: query }],
stream: true,
max_tokens: 4096,
});
let fullText = "";
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content || "";
fullText += text;
onChunk(text);
if ((chunk as any).citations) {
onCitations((chunk as any).citations);
}
}
return fullText;
}