Guides
Best Practices

Best Practices

Tips and patterns for getting the most out of Hypersave.

Content Management

Optimize What You Save

Save meaningful content, not everything:

// Good: Focused, meaningful content
await save({
  content: "The Q4 budget was approved at $2.5M with 60% allocated to engineering",
  title: "Q4 Budget Decision",
  tags: ["budget", "finance", "q4"]
});
 
// Avoid: Raw, unstructured data
await save({
  content: "[10:23] user joined\n[10:24] user: hi\n[10:24] bot: hello..."
});

Use Structured Metadata

await save({
  content: "...",
  metadata: {
    source: "meeting-notes",
    participants: ["john", "jane"],
    date: "2024-01-15",
    project: "website-redesign",
    actionItems: 3
  }
});

Consistent Tagging

Establish a tagging convention:

const TAGS = {
  type: ['meeting', 'research', 'decision', 'idea'],
  status: ['active', 'archived', 'pending'],
  priority: ['high', 'medium', 'low'],
  team: ['engineering', 'product', 'design', 'sales']
};
 
// Apply consistently
await save({
  content: "...",
  tags: ['type:meeting', 'team:engineering', 'priority:high']
});

Search Optimization

Use Hybrid Search

For most queries, hybrid search (semantic + keyword) gives best results:

const results = await search({
  query: "TypeScript configuration",
  hybrid: true,  // Combine semantic and keyword
  threshold: 0.6
});

Filter Strategically

Narrow down results with filters:

// Search only recent, high-priority items
const results = await search({
  query: "deployment issues",
  tags: ["priority:high"],
  after: "2024-01-01"
});

Set Appropriate Thresholds

// High precision (fewer but more relevant results)
const preciseResults = await search({
  query: "exact technical spec",
  threshold: 0.85
});
 
// High recall (more results, some less relevant)
const broadResults = await search({
  query: "general topic exploration",
  threshold: 0.5
});

Performance

Use Turbo Mode for Speed

When you need fast responses and don't need full processing:

// Real-time chat: use turbo
await turboSave({ content: quickNote });
 
// Important document: use standard
await save({ content: importantDoc });

Batch Operations

Use bulk endpoints for multiple items:

// Good: Single batch request
await ingest({
  items: documents,
  async: true
});
 
// Avoid: Multiple individual requests
for (const doc of documents) {
  await save(doc);  // Slower, uses more quota
}

Implement Caching

Cache frequent queries:

const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
 
async function cachedSearch(query) {
  const cacheKey = JSON.stringify(query);
 
  if (cache.has(cacheKey)) {
    const { data, timestamp } = cache.get(cacheKey);
    if (Date.now() - timestamp < CACHE_TTL) {
      return data;
    }
  }
 
  const results = await search(query);
  cache.set(cacheKey, { data: results, timestamp: Date.now() });
  return results;
}

Security

Protect API Keys

⚠️

Never expose API keys in client-side code or version control.

// Server-side only
const API_KEY = process.env.HYPERSAVE_API_KEY;
 
// Create a backend proxy for client requests
app.post('/api/search', async (req, res) => {
  const results = await hypersave.search(req.body);
  res.json(results);
});

User Data Isolation

Use tags or spaces to isolate user data:

// Tag-based isolation
async function searchUserContent(query, userId) {
  return search({
    query,
    tags: [`user:${userId}`]  // Only returns user's content
  });
}
 
// Space-based isolation
async function saveUserContent(content, userId) {
  return save({
    content,
    spaceId: `user_${userId}_space`
  });
}

Rate Limiting

Implement rate limiting to prevent abuse:

const rateLimit = require('express-rate-limit');
 
const limiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 60, // 60 requests per minute
  message: { error: 'Too many requests' }
});
 
app.use('/api', limiter);

Error Handling

Graceful Degradation

Handle API errors gracefully:

async function searchWithFallback(query) {
  try {
    const results = await search({ query });
    return results;
  } catch (error) {
    if (error.status === 429) {
      // Rate limited: return cached results or wait
      console.warn('Rate limited, using cache');
      return getCachedResults(query);
    }
    if (error.status >= 500) {
      // Server error: use fallback
      console.error('Hypersave unavailable');
      return { results: [], error: 'Search temporarily unavailable' };
    }
    throw error;
  }
}

Retry Logic

Implement exponential backoff:

async function withRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
 
      const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
 
// Usage
const results = await withRetry(() => search({ query: 'test' }));

Monitoring

Track Usage

Monitor your API usage:

async function trackUsage() {
  const usage = await fetch(`${API}/v1/usage`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  }).then(r => r.json());
 
  if (usage.limits.usedPercentage > 80) {
    alert('Approaching usage limit');
  }
 
  return usage;
}

Log Requests

Log API calls for debugging:

async function loggedRequest(endpoint, options) {
  const start = Date.now();
 
  try {
    const response = await fetch(endpoint, options);
    const duration = Date.now() - start;
 
    console.log({
      endpoint,
      status: response.status,
      duration,
      timestamp: new Date().toISOString()
    });
 
    return response;
  } catch (error) {
    console.error({ endpoint, error: error.message });
    throw error;
  }
}