Pinecone Projects let you isolate your indexes and their associated data, effectively creating separate environments for different teams or applications within your Pinecone account.
Let’s see this in action. Imagine you’re managing a recommendation engine for two distinct product lines: "Apparel" and "Electronics." Without Projects, all your recommendation indexes would live in one flat list, potentially leading to naming conflicts and making it hard to manage permissions and costs per team.
Here’s how you might set it up using the Pinecone Python client:
from pinecone import Pinecone, Project
# Initialize Pinecone
# Ensure you have your API key and environment set as environment variables
pc = Pinecone()
# Create Projects for each team
try:
apparel_project = pc.create_project(name="apparel-team", description="Indexes for the Apparel product line")
print(f"Created project: {apparel_project.name}")
except Exception as e:
print(f"Error creating project: {e}")
# If project already exists, get it
apparel_project = pc.get_project(name="apparel-team")
try:
electronics_project = pc.create_project(name="electronics-team", description="Indexes for the Electronics product line")
print(f"Created project: {electronics_project.name}")
except Exception as e:
print(f"Error creating project: {e}")
# If project already exists, get it
electronics_project = pc.get_project(name="electronics-team")
# Now, create indexes within their respective projects
# For Apparel:
apparel_index_name = "apparel-recs"
if apparel_index_name not in pc.list_indexes(project_name="apparel-team"):
pc.create_index(
name=apparel_index_name,
dimension=1536, # Example dimension
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1"),
project_name="apparel-team"
)
print(f"Created index '{apparel_index_name}' in 'apparel-team' project.")
else:
print(f"Index '{apparel_index_name}' already exists in 'apparel-team' project.")
# For Electronics:
electronics_index_name = "electronics-recs"
if electronics_index_name not in pc.list_indexes(project_name="electronics-team"):
pc.create_index(
name=electronics_index_name,
dimension=1536, # Example dimension
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1"),
project_name="electronics-team"
)
print(f"Created index '{electronics_index_name}' in 'electronics-team' project.")
else:
print(f"Index '{electronics_index_name}' already exists in 'electronics-team' project.")
# You can then interact with indexes scoped to a project
# Example: Upserting data into the apparel index
# Assuming you have an index object for apparel_index_name within the apparel_project
apparel_index = pc.Index(apparel_index_name, project_name="apparel-team")
apparel_index.upsert(vectors=[("vec1", [0.1]*1536, {"genre": "casual"})])
print("Upserted data into apparel index.")
# Example: Querying the electronics index
electronics_index = pc.Index(electronics_index_name, project_name="electronics-team")
query_results = electronics_index.query(vector=[0.2]*1536, top_k=5, include_metadata=True)
print("Queried electronics index.")
This code demonstrates the core idea: you first create distinct Project objects, and then when you create or interact with indexes, you pass the project_name argument. This scopes the operation to that specific project. Listing indexes will now show only those within the specified project, and API calls will only operate on resources within that project.
The fundamental problem Projects solve is multi-tenancy and resource segregation at the account level. Before Projects, a single Pinecone account was a single namespace. If you had multiple teams or applications, you had to manage this separation manually through naming conventions and careful access control. Projects provide a built-in, auditable way to divide your Pinecone resources. Each project has its own set of indexes, and you can control access at the project level, ensuring that Team A can’t accidentally (or intentionally) see or modify Team B’s data. This also simplifies cost allocation, as you can see usage per project.
When you create a project, you’re essentially creating a new, isolated namespace within your Pinecone account. When you then create an index, you associate it with a specific project by providing the project_name parameter. This association is key. Any subsequent operations on that index (creating, deleting, upserting, querying) must be performed with a reference to that project. This is why you see project_name="apparel-team" or project_name="electronics-team" in the create_index, list_indexes, and Index constructor calls.
A subtle but powerful aspect of Projects is how they interact with API keys and permissions. While a single API key can access all projects within an account by default, you can implement more granular access control using roles and permissions tied to specific projects. This means you can grant a user or service account read-only access to the "Apparel" project but full access to the "Electronics" project, all within the same Pinecone account. This is achieved through the Pinecone console’s "Access Control" settings, where you can define users, assign them roles, and then associate those roles with specific projects.
The next natural step after organizing your indexes by team is to consider how to manage different versions of your models or data within those teams, often leading to exploring techniques for index versioning or distinct index lifecycles.