Legacy guide for managing Pinecone pod-based indexes. Pod indexes are no longer available to new customers as of August 2025. Serverless indexes are recommended for all new projects.
Customers who sign up for a Standard or Enterprise plan on or after August 18, 2025 cannot create pod-based indexes. Instead, create serverless indexes, and consider using dedicated read nodes for large workloads (millions of records or more, and moderate or high query rates).
This page shows you how to manage pod-based indexes.For guidance on serverless indexes, see Manage serverless indexes.
Do not target an index by name in production.When you target an index by name for data operations such as upsert and query, the SDK gets the unique DNS host for the index using the describe_index operation. This is convenient for testing but should be avoided in production because describe_index uses a different API than data operations and therefore adds an additional network call and point of failure. Instead, you should get an index host once and cache it for reuse or specify the host directly.
// npm install @pinecone-database/pineconeimport { Pinecone } from '@pinecone-database/pinecone'const pc = new Pinecone({ apiKey: 'YOUR_API_KEY'});await pc.deleteIndex('docs-example');
import io.pinecone.clients.Pinecone;public class DeleteIndexExample { public static void main(String[] args) { Pinecone pc = new Pinecone.Builder("YOUR_API_KEY").build(); pc.deleteIndex("docs-example"); }}
You can delete an index using the Pinecone console. For the index you want to delete, click the three dots to the right of the index name, then click Delete.
For pod-based indexes, Pinecone indexes all metadata fields by default. When metadata fields contains many unique values, pod-based indexes will consume significantly more memory, which can lead to performance issues, pod fullness, and a reduction in the number of possible vectors that fit per pod.To avoid indexing high-cardinality metadata that is not needed for filtering your queries and keep memory utilization low, specify which metadata fields to index using the metadata_config parameter.
Since high-cardinality metadata does not cause high memory utilization in serverless indexes, selective metadata indexing is not supported.
The value for the metadata_config parameter is a JSON object containing the names of the metadata fields to index.
ExampleThe following example creates a pod-based index that only indexes the genre metadata field. Queries against this index that filter for the genre metadata field may return results; queries that filter for other metadata fields behave as though those fields do not exist.
You can prevent an index and its data from accidental deleting when creating a new index or when configuring an existing index. In both cases, you set the deletion_protection parameter to enabled.To enable deletion protection when creating a new index:
To enable deletion protection when configuring an existing index:
from pinecone.grpc import PineconeGRPC as Pineconepc = Pinecone(api_key="YOUR_API_KEY")pc.configure_index( name="docs-example", deletion_protection="enabled")
import { Pinecone } from '@pinecone-database/pinecone';const client = new Pinecone({ apiKey: 'YOUR_API_KEY' });await client.configureIndex('docs-example', { deletionProtection: 'enabled' });
import io.pinecone.clients.Pinecone;import org.openapitools.db_control.client.model.*;public class ConfigureIndexExample { public static void main(String[] args) { Pinecone pc = new Pinecone.Builder("YOUR_API_KEY").build(); pc.configurePodsIndex("docs-example", DeletionProtection.ENABLED); }}
package mainimport ( "context" "fmt" "log" "github.com/pinecone-io/go-pinecone/v4/pinecone")func main() { ctx := context.Background() pc, err := pinecone.NewClient(pinecone.NewClientParams{ ApiKey: "YOUR_API_KEY", }) if err != nil { log.Fatalf("Failed to create Client: %v", err) } idx, err := pc.ConfigureIndex(ctx, "docs-example", pinecone.ConfigureIndexParams{DeletionProtection: "enabled"}) if err != nil { log.Fatalf("Failed to configure index \"%v\": %v", idx.Name, err) } else { fmt.Printf("Successfully configured index \"%v\"", idx.Name) }}
Before you can delete an index with deletion protection enabled, you must first disable deletion protection as follows:
from pinecone.grpc import PineconeGRPC as Pineconepc = Pinecone(api_key="YOUR_API_KEY")pc.configure_index( name="docs-example", deletion_protection="disabled")
import { Pinecone } from '@pinecone-database/pinecone';const client = new Pinecone({ apiKey: 'YOUR_API_KEY' });await client.configureIndex('docs-example', { deletionProtection: 'disabled' });
import io.pinecone.clients.Pinecone;import org.openapitools.db_control.client.model.*;public class ConfigureIndexExample { public static void main(String[] args) { Pinecone pc = new Pinecone.Builder("YOUR_API_KEY").build(); pc.configurePodsIndex("docs-example", DeletionProtection.DISABLED); }}
package mainimport ( "context" "fmt" "log" "github.com/pinecone-io/go-pinecone/v4/pinecone")func main() { ctx := context.Background() pc, err := pinecone.NewClient(pinecone.NewClientParams{ ApiKey: "YOUR_API_KEY", }) if err != nil { log.Fatalf("Failed to create Client: %v", err) } idx, err := pc.ConfigureIndex(ctx, "docs-example", pinecone.ConfigureIndexParams{DeletionProtection: "disabled"}) if err != nil { log.Fatalf("Failed to configure index \"%v\": %v", idx.Name, err) } else { fmt.Printf("Successfully configured index \"%v\"", idx.Name) }}
In pod-based indexes, reads and writes share compute resources, so deleting an entire namespace with many records can increase the latency of read operations. In such cases, consider deleting records in batches.
In pod-based indexes, reads and writes share compute resources, so deleting an entire namespace or a large number of records can increase the latency of read operations. To avoid this, delete records in batches of up to 1000, with a brief sleep between requests. Consider using smaller batches if the index has active read traffic.
from pinecone import Pineconeimport numpy as npimport timepc = Pinecone(api_key='API_KEY')INDEX_NAME = 'INDEX_NAME'NAMESPACE = 'NAMESPACE_NAME'# Consider using smaller batches if you have a high RPS for read operationsBATCH = 1000index = pc.Index(name=INDEX_NAME)dimensions = index.describe_index_stats()['dimension']# Create the query vectorquery_vector = np.random.uniform(-1, 1, size=dimensions).tolist()results = index.query(vector=query_vector, namespace=NAMESPACE, top_k=BATCH)# Delete in batches until the query returns no resultswhile len(results['matches']) > 0: ids = [i['id'] for i in results['matches']] index.delete(ids=ids, namespace=NAMESPACE) time.sleep(0.01) results = index.query(vector=query_vector, namespace=NAMESPACE, top_k=BATCH)
from pinecone import Pineconeimport numpy as npimport timepc = Pinecone(api_key='API_KEY')INDEX_NAME = 'INDEX_NAME'NAMESPACE = 'NAMESPACE_NAME'# Consider using smaller batches if you have a high RPS for read operationsBATCH = 1000index = pc.Index(name=INDEX_NAME)dimensions = index.describe_index_stats()['dimension']METADATA_FILTER = {}# Create the query vector with a filterquery_vector = np.random.uniform(-1, 1, size=dimensions).tolist()results = index.query(vector=query_vector, namespace=NAMESPACE, filter=METADATA_FILTER, top_k=BATCH)# Delete in batches until the query returns no resultswhile len(results['matches']) > 0: ids = [i['id'] for i in results['matches']] index.delete(ids=ids, namespace=NAMESPACE) time.sleep(0.01) results = index.query(vector=query_vector, namespace=NAMESPACE, filter=METADATA_FILTER, top_k=BATCH)
In pod-based indexes, if you are targeting a large number of records for deletion and the index has active read traffic, consider deleting records in batches.
To delete records from a namespace based on their metadata values, pass a metadata filter expression to the delete operation. This deletes all records in the namespace that match the filter expression.For example, the following code deletes all records with a genre field set to documentary from namespace example-namespace:
# pip install "pinecone[grpc]"from pinecone.grpc import PineconeGRPC as Pineconepc = Pinecone(api_key="YOUR_API_KEY")# To get the unique host for an index, # see https://docs.pinecone.io/guides/manage-data/target-an-indexindex = pc.Index(host="INDEX_HOST")index.delete( filter={ "genre": {"$eq": "documentary"} }, namespace="example-namespace")
import { Pinecone } from '@pinecone-database/pinecone'const pc = new Pinecone({ apiKey: "YOUR_API_KEY" })// To get the unique host for an index, // see https://docs.pinecone.io/guides/manage-data/target-an-indexconst index = pc.index("INDEX_NAME", "INDEX_HOST")const ns = index.namespace('example-namespace')await ns.deleteMany({ genre: { $eq: "documentary" },});
import com.google.protobuf.Struct;import com.google.protobuf.Value;import io.pinecone.clients.Index;import io.pinecone.configs.PineconeConfig;import io.pinecone.configs.PineconeConnection;import java.util.Arrays;import java.util.List;public class DeleteExample { public static void main(String[] args) { PineconeConfig config = new PineconeConfig("YOUR_API_KEY"); // To get the unique host for an index, // see https://docs.pinecone.io/guides/manage-data/target-an-index config.setHost("INDEX_HOST"); PineconeConnection connection = new PineconeConnection(config); Index index = new Index(connection, "INDEX_NAME"); Struct filter = Struct.newBuilder() .putFields("genre", Value.newBuilder() .setStructValue(Struct.newBuilder() .putFields("$eq", Value.newBuilder() .setStringValue("documentary") .build())) .build()) .build(); index.deleteByFilter(filter, "example-namespace"); }}
package mainimport ( "context" "log" "github.com/pinecone-io/go-pinecone/v4/pinecone")func main() { ctx := context.Background() pc, err := pinecone.NewClient(pinecone.NewClientParams{ ApiKey: "YOUR_API_KEY", }) if err != nil { log.Fatalf("Failed to create Client: %v", err) } // To get the unique host for an index, // see https://docs.pinecone.io/guides/manage-data/target-an-index idxConnection, err := pc.Index(pinecone.NewIndexConnParams{Host: "INDEX_HOST", Namespace: "example-namespace"}) if err != nil { log.Fatalf("Failed to create IndexConnection for Host: %v", err) } metadataFilter := map[string]interface{}{ "genre": map[string]interface{}{ "$eq": "documentary", }, } filter, err := structpb.NewStruct(metadataFilter) if err != nil { log.Fatalf("Failed to create metadata filter: %v", err) } err = idxConnection.DeleteVectorsByFilter(ctx, filter) if err != nil { log.Fatalf("Failed to delete vector(s) with filter %+v: %v", filter, err) }}
# To get the unique host for an index,# see https://docs.pinecone.io/guides/manage-data/target-an-indexPINECONE_API_KEY="YOUR_API_KEY"INDEX_HOST="INDEX_HOST"curl -i "https://$INDEX_HOST/vectors/delete" \ -H 'Api-Key: $PINECONE_API_KEY' \ -H 'Content-Type: application/json' \ -H "X-Pinecone-Api-Version: 2025-10" \ -d '{ "filter": {"genre": {"$eq": "documentary"}}, "namespace": "example-namespace" }'
For each pod-based index, billing is determined by the per-minute price per pod and the number of pods the index uses, regardless of index activity. When a pod-based index is not in use, back it up using collections and delete the inactive index. When you’re ready to use the vectors again, you can create a new index from the collection. This new index can also use a different index type or size. Because it’s relatively cheap to store collections, you can reduce costs by only running an index when it’s in use.
Pod sizes are designed for different applications, and some are more expensive than others. Choose the appropriate pod type and size, so you pay for the resources you need. For example, the s1 pod type provides large storage capacity and lower overall costs with slightly higher query latencies than p1 pods. By switching to a different pod type, you may be able to reduce costs while still getting the performance your application needs.
Pinecone generates time-series performance metrics for each Pinecone index. You can monitor these metrics directly in the Pinecone console or with tools like Prometheus or Datadog.
To monitor all pod-based indexes in a specific region of a project, insert the following snippet into the scrape_configs section of your prometheus.yml file and update it with values for your Prometheus integration:
Serverless indexes automatically scale as needed.However, pod-based indexes can run out of capacity. When that happens, upserting new records will fail with the following error:
The first scenario involves customers loading an index replete with high cardinality metadata. This can trigger a series of unforeseen challenges, and hence, it’s vital to comprehend how to manage this situation effectively. This methodology can be applied whenever you need to change your metadata configuration.
The second scenario that we will address involves customers who have over-provisioned the number of pods they need. More specifically, we will discuss the process of re-scaling an index in instances where the customer has previously scaled vertically and now desires to scale the index back down.