OptionalMLOpsVersion 1.0.1

Pinecone Managed Vector Database: Setup, Operations, and Integrations

Managed vector DB for production RAG and search.

Written by Neura Market from the official Hermes Agent documentation for Pinecone. Commands, paths, and version numbers are reproduced from the source unchanged.

Read the official documentation

Pinecone is a fully managed, serverless vector database built for production AI workloads. You reach for it when you need low-latency similarity search at scale without running your own infrastructure. This guide covers installation, core operations, hybrid search, and integrations with LangChain and LlamaIndex.

What it does

Pinecone stores and retrieves vector embeddings alongside metadata. It handles auto-scaling, replication, and indexing so you can focus on building retrieval-augmented generation (RAG) pipelines, recommendation systems, or semantic search. The service guarantees p95 latency under 100ms and a 99.9% uptime SLA. You interact with it through a Python SDK that supports upsert, query, metadata filtering, and namespace partitioning.

Before you start

You need a Pinecone account and an API key from the Pinecone console. The SDK runs on Linux, macOS, and Windows. Install the current package (v5+; the old pinecone-client is deprecated):

pip install pinecone

Note: the old pinecone-client package is deprecated. Install pinecone (v5+; current 9.x). The import stays from pinecone import Pinecone.

Quick start

Initialize the client, create a serverless index, upsert a few vectors, and run a query.

from pinecone import Pinecone, ServerlessSpec

# Initialize
pc = Pinecone(api_key="your-api-key")

# Create index
pc.create_index(
    name="my-index",
    dimension=1536,  # Must match embedding dimension
    metric="cosine",  # or "euclidean", "dotproduct"
    spec=ServerlessSpec(cloud="aws", region="us-east-1")
)

# Connect to index
index = pc.Index("my-index")

# Upsert vectors
index.upsert(vectors=[
    {"id": "vec1", "values": [0.1, 0.2, ...], "metadata": {"category": "A"}},
    {"id": "vec2", "values": [0.3, 0.4, ...], "metadata": {"category": "B"}}
])

# Query
results = index.query(
    vector=[0.1, 0.2, ...],
    top_k=5,
    include_metadata=True
)

print(results["matches"])

Core operations

Create index

You can create a serverless index (recommended for most use cases) or a pod-based index for consistent performance under predictable workloads.

# Serverless (recommended)
pc.create_index(
    name="my-index",
    dimension=1536,
    metric="cosine",
    spec=ServerlessSpec(
        cloud="aws",         # or "gcp", "azure"
        region="us-east-1"
    )
)

# Pod-based (for consistent performance)
from pinecone import PodSpec

pc.create_index(
    name="my-index",
    dimension=1536,
    metric="cosine",
    spec=PodSpec(
        environment="us-east1-gcp",
        pod_type="p1.x1"
    )
)

Upsert vectors

Upsert adds or updates vectors. Batch upserts are more efficient than single ones.

# Single upsert
index.upsert(vectors=[
    {
        "id": "doc1",
        "values": [0.1, 0.2, ...],  # 1536 dimensions
        "metadata": {
            "text": "Document content",
            "category": "tutorial",
            "timestamp": "2025-01-01"
        }
    }
])

# Batch upsert (recommended)
vectors = [
    {"id": f"vec{i}", "values": embedding, "metadata": metadata}
    for i, (embedding, metadata) in enumerate(zip(embeddings, metadatas))
]

index.upsert(vectors=vectors, batch_size=100)

Query vectors

Query returns the nearest neighbors. You can filter by metadata, scope to a namespace, and control which fields are returned.

# Basic query
results = index.query(
    vector=[0.1, 0.2, ...],
    top_k=10,
    include_metadata=True,
    include_values=False
)

# With metadata filtering
results = index.query(
    vector=[0.1, 0.2, ...],
    top_k=5,
    filter={"category": {"$eq": "tutorial"}}
)

# Namespace query
results = index.query(
    vector=[0.1, 0.2, ...],
    top_k=5,
    namespace="production"
)

# Access results
for match in results["matches"]:
    print(f"ID: {match['id']}")
    print(f"Score: {match['score']}")
    print(f"Metadata: {match['metadata']}")

Metadata filtering

Filters narrow results before similarity scoring. Supported operators include exact match, comparison, logical, and $in.

# Exact match
filter = {"category": "tutorial"}

# Comparison
filter = {"price": {"$gte": 100}}  # $gt, $gte, $lt, $lte, $ne

# Logical operators
filter = {
    "$and": [
        {"category": "tutorial"},
        {"difficulty": {"$lte": 3}}
    ]
}  # Also: $or

# In operator
filter = {"tags": {"$in": ["python", "ml"]}}

Namespaces

Namespaces let you partition data within a single index, useful for multi-tenant setups or separating environments.

# Partition data by namespace
index.upsert(
    vectors=[{"id": "vec1", "values": [...]}],
    namespace="user-123"
)

# Query specific namespace
results = index.query(
    vector=[...],
    namespace="user-123",
    top_k=5
)

# List namespaces
stats = index.describe_index_stats()
print(stats['namespaces'])

Hybrid search (dense + sparse)

Hybrid search combines dense embeddings with sparse vectors (e.g., TF-IDF) for better retrieval quality. Note that index.query() does not accept an alpha parameter; you must scale the query vectors yourself before sending them.

# Upsert with sparse vectors
index.upsert(vectors=[
    {
        "id": "doc1",
        "values": [0.1, 0.2, ...],  # Dense vector
        "sparse_values": {
            "indices": [10, 45, 123],  # Token IDs
            "values": [0.5, 0.3, 0.8]   # TF-IDF scores
        },
        "metadata": {"text": "..."}
    }
])

# Hybrid query
# NOTE: index.query() does NOT accept an `alpha` kwarg. Pinecone stores a
# single sparse-dense vector, so weighting must be applied by pre-scaling the
# query vectors before sending them. Use the hybrid_score_norm helper below
# (alpha * dense + (1 - alpha) * sparse; alpha=1 → pure dense, 0 → pure sparse).

def hybrid_score_norm(dense, sparse, alpha: float):
    """Scale dense/sparse query vectors for weighted hybrid search."""
    if not 0 <= alpha <= 1:
        raise ValueError("alpha must be between 0 and 1")
    scaled_sparse = {
        "indices": sparse["indices"],
        "values": [v * (1 - alpha) for v in sparse["values"]],
    }
    return [v * alpha for v in dense], scaled_sparse

hdense, hsparse = hybrid_score_norm(
    dense=[0.1, 0.2, ...],
    sparse={"indices": [10, 45], "values": [0.5, 0.3]},
    alpha=0.5,  # 0=sparse, 1=dense, 0.5=balanced
)

results = index.query(
    vector=hdense,
    sparse_vector=hsparse,
    top_k=5,
)

LangChain integration

Pinecone works as a vector store in LangChain, supporting document ingestion, similarity search, and retriever creation.

from langchain_pinecone import PineconeVectorStore
from langchain_openai import OpenAIEmbeddings

# Create vector store
vectorstore = PineconeVectorStore.from_documents(
    documents=docs,
    embedding=OpenAIEmbeddings(),
    index_name="my-index"
)

# Query
results = vectorstore.similarity_search("query", k=5)

# With metadata filter
results = vectorstore.similarity_search(
    "query",
    k=5,
    filter={"category": "tutorial"}
)

# As retriever
retriever = vectorstore.as_retriever(search_kwargs={"k": 10})

LlamaIndex integration

Connect Pinecone to LlamaIndex for document indexing and querying.

from llama_index.vector_stores.pinecone import PineconeVectorStore

# Connect to Pinecone
pc = Pinecone(api_key="your-key")
pinecone_index = pc.Index("my-index")

# Create vector store
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)

# Use in LlamaIndex
from llama_index.core import StorageContext, VectorStoreIndex

storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

Index management

List, describe, and delete indices. Use describe_index_stats to monitor vector counts and namespaces.

# List indices
indexes = pc.list_indexes()

# Describe index
index_info = pc.describe_index("my-index")
print(index_info)

# Get index stats
stats = index.describe_index_stats()
print(f"Total vectors: {stats['total_vector_count']}")
print(f"Namespaces: {stats['namespaces']}")

# Delete index
pc.delete_index("my-index")

Delete vectors

Remove vectors by ID, filter, namespace, or wipe the entire index.

# Delete by ID
index.delete(ids=["vec1", "vec2"])

# Delete by filter
index.delete(filter={"category": "old"})

# Delete all in namespace
index.delete(delete_all=True, namespace="test")

# Delete entire index
index.delete(delete_all=True)

Best practices

  1. Use serverless - Auto-scaling, cost-effective
  2. Batch upserts - More efficient (100-200 per batch)
  3. Add metadata - Enable filtering
  4. Use namespaces - Isolate data by user/tenant
  5. Monitor usage - Check Pinecone dashboard
  6. Optimize filters - Index frequently filtered fields
  7. Test with free tier - 1 index, 100K vectors free
  8. Use hybrid search - Better quality
  9. Set appropriate dimensions - Match embedding model
  10. Regular backups - Export important data

Performance

OperationLatencyNotes
Upsert~50-100msPer batch
Query (p50)~50msDepends on index size
Query (p95)~100msSLA target
Metadata filter~+10-20msAdditional overhead

Pricing (as of 2025)

Serverless:

  • $0.096 per million read units
  • $0.06 per million write units
  • $0.06 per GB storage/month

Free tier:

  • 1 serverless index
  • 100K vectors (1536 dimensions)
  • Great for prototyping

When not to use it

If you need a self-hosted, open-source solution, consider Chroma or Weaviate. For offline, pure similarity search without a database, FAISS is a better fit. Pinecone is a managed SaaS service, so you trade infrastructure control for operational simplicity.

Limits and gotchas

  • The index.query() method does not accept an alpha parameter for hybrid search; you must pre-scale vectors using the hybrid_score_norm helper shown above.
  • The old pinecone-client package is deprecated. Use pinecone (v5+).
  • Index dimension must match your embedding model's output size.
  • Metadata filtering adds ~10-20ms overhead per query.

Resources

More MLOps skills