Skip to main content

Best Practices

Follow these best practices to build robust and efficient applications.

Security

Protect Your API Keys

  • Never commit API keys to version control
  • Use environment variables for sensitive data
  • Rotate keys regularly
  • Use different keys for development and production
// Good ✅
const client = new Client({
apiKey: process.env.API_KEY
});

// Bad ❌
const client = new Client({
apiKey: 'sk_live_abc123...'
});

Validate Input

Always validate and sanitize user input before sending to the API:

function validatePrompt(prompt) {
if (typeof prompt !== 'string') {
throw new Error('Prompt must be a string');
}
if (prompt.length > 10000) {
throw new Error('Prompt too long');
}
return prompt.trim();
}

Performance

Use Streaming for Long Responses

For better user experience, stream responses instead of waiting for completion:

const stream = await client.generateStream({ prompt });
for await (const chunk of stream) {
updateUI(chunk.text);
}

Implement Caching

Cache responses when appropriate to reduce API calls:

const cache = new Map();

async function cachedGenerate(prompt) {
if (cache.has(prompt)) {
return cache.get(prompt);
}
const result = await client.generate({ prompt });
cache.set(prompt, result);
return result;
}

Batch Requests

Group multiple requests when possible to reduce latency:

const results = await Promise.all(
prompts.map(p => client.generate({ prompt: p }))
);

Error Handling

Implement Retry Logic

Handle transient failures with exponential backoff:

async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
if (error.status >= 500 || error.status === 429) {
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
} else {
throw error;
}
}
}
}

Handle Rate Limits

Monitor and respect rate limits:

class RateLimitedClient {
constructor(client, requestsPerMinute) {
this.client = client;
this.queue = [];
this.interval = 60000 / requestsPerMinute;
}

async generate(params) {
return new Promise((resolve, reject) => {
this.queue.push({ params, resolve, reject });
this.processQueue();
});
}

processQueue() {
if (this.queue.length === 0) return;
const { params, resolve, reject } = this.queue.shift();
this.client.generate(params)
.then(resolve)
.catch(reject);
setTimeout(() => this.processQueue(), this.interval);
}
}

Monitoring

Log API Usage

Track your API usage and performance:

const startTime = Date.now();
try {
const result = await client.generate({ prompt });
const duration = Date.now() - startTime;
console.log(`Request completed in ${duration}ms`);
console.log(`Tokens used: ${result.usage.totalTokens}`);
} catch (error) {
console.error('Request failed:', error);
}

Set Timeouts

Always set appropriate timeouts:

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30000);

try {
const result = await client.generate(
{ prompt },
{ signal: controller.signal }
);
} finally {
clearTimeout(timeout);
}

Testing

Mock API Calls

Use mocks in your tests:

import { jest } from '@jest/globals';

const mockClient = {
generate: jest.fn().mockResolvedValue({
text: 'Mocked response',
usage: { totalTokens: 10 }
})
};

Next Steps