You should create a single Pinecone client instance and reuse it throughout your application rather than creating a new instance for every operation.
Benefits of reusing the client:
// ✅ Good: Reuse client instance
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
async function query1() {
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
return await index.query({ vector: [0.1, 0.2], topK: 10 });
}
async function query2() {
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
return await index.query({ vector: [0.2, 0.3], topK: 10 });
}
// ❌ Bad: Creating new client for each operation
async function badQuery() {
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' }); // Don't do this repeatedly!
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
return await index.query({ vector: [0.1, 0.2], topK: 10 });
}
No network requests are made when instantiating the client with new Pinecone(). Network requests only occur when you invoke operations like upsert, query, pc.indexes.list, etc.
The SDK uses the native fetch API (available in Node.js 18+ and Edge runtimes), which handles HTTP connection management automatically.
Both approaches are valid. Choose based on your deployment strategy:
Environment variables (recommended for production):
import { Pinecone } from '@pinecone-database/pinecone';
// Reads from PINECONE_API_KEY environment variable
const pc = new Pinecone();
Configuration object (useful for testing or multi-project scenarios):
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({
apiKey: 'YOUR_API_KEY',
maxRetries: 5,
});
Best practice for production: Always target indexes by host to avoid an additional network call and potential point of failure.
When you target an index by name, the SDK automatically calls describeIndex() to resolve the host URL. This is convenient for testing but should be avoided in production:
// Testing: convenient but makes extra API call
const index = pc.index({ name: 'my-index' });
For production, get the index host from describeIndex() or from the create response, then target by host directly:
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
Or get the host when creating an index:
const indexModel = await pc.indexes.create({
name: 'my-index',
dimension: 1536,
spec: { serverless: { cloud: 'aws', region: 'us-east-1' } },
});
const index = pc.index({ host: indexModel.host });
For more details, see Target an index.
Call listIndexes() to verify connectivity and API key validity:
import { Pinecone } from '@pinecone-database/pinecone';
async function verifyConnection() {
try {
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexes = await pc.indexes.list();
console.log(
'Connection successful! Indexes:',
indexes.indexes?.length ?? 0,
);
} catch (error) {
console.error('Connection failed:', error);
}
}
verifyConnection();
The SDK requires TypeScript >=5.2.0 and Node.js >=22.0.0.
You must also have @types/node installed as a dev dependency:
npm install --save-dev @types/node
Common causes and solutions:
npm install --save-dev @types/node
Check your TypeScript version:
npx tsc --version
Upgrade if needed:
npm install --save-dev typescript@latest
Enable strict null checking in tsconfig.json:
{
"compilerOptions": {
"strict": true,
"strictNullChecks": true
}
}
The SDK's published type declarations reference DOM lib types (for example RequestCredentials,
WindowOrWorkerGlobalScope, used by the fetchApi configuration option and its underlying
FetchAPI type). A tsconfig.json that doesn't set "skipLibCheck": true and whose lib array
omits "dom" and "webworker" will fail to compile against these declarations, even though the
SDK itself runs fine in Node.js. Add "webworker" (or "dom") to lib, or set "skipLibCheck": true, to resolve this.
No. The Pinecone TypeScript SDK is intended for server-side use only. Using the SDK in a browser can expose your API key.
Supported environments:
Batch your upserts for optimal performance:
import { Pinecone, PineconeRecord } from '@pinecone-database/pinecone';
async function batchUpsert(records: PineconeRecord[], batchSize: number = 100) {
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
for (let i = 0; i < records.length; i += batchSize) {
const batch = records.slice(i, i + batchSize);
await index.upsert({ records: batch });
console.log(`Upserted ${i + batch.length} / ${records.length} records`);
}
}
For very large datasets (millions of vectors), consider using the bulk import feature.
Common causes and solutions:
Pinecone client instance to avoid unnecessary instantiation overheadhost instead of name to avoid extra API callsincludeValues: false and includeMetadata: false if not neededSee the performance tuning guide for more optimization strategies.
The SDK handles concurrent requests safely. Use Promise.all for parallel operations:
import { Pinecone } from '@pinecone-database/pinecone';
async function concurrentQueries() {
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
const queries = [
[0.1, 0.2, 0.3],
[0.2, 0.3, 0.4],
[0.3, 0.4, 0.5],
];
// Execute all queries in parallel
const results = await Promise.all(
queries.map((vector) =>
index.query({
vector,
topK: 10,
}),
),
);
return results;
}
concurrentQueries();
upsert, upsertRecords, and documents.upsert?upsert: For vectors you've already embedded (bring your own vectors)upsertRecords: For text data with integrated inference (Pinecone generates embeddings)documents.upsert: For documents with _id and named text or vector fields defined by an index schema. Full-text search uses text directly; you supply any dense or sparse vector values yourself.Choose the operation that matches your index schema. See Working with Documents for document upserts and full-text search.
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
// Use upsert when you have vectors
const index1 = pc.index({ name: 'byov-index' });
await index1.upsert({
records: [{ id: '1', values: [0.1, 0.2, 0.3] }],
});
// Use upsertRecords with integrated inference indexes
const index2 = pc.index({ name: 'integrated-index' });
await index2.upsertRecords({
records: [{ id: '1', text: 'This text will be embedded automatically' }],
});
Yes, you can provide a custom fetch implementation that supports proxies:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({
apiKey: 'YOUR_API_KEY',
fetchApi: customFetchWithProxy, // Your custom fetch implementation
});
For Node.js environments, you can use libraries like undici or node-fetch with proxy agents. Refer to your proxy library's documentation for configuration details.