Skip to main content
This page shows you how to upsert documents and records into a namespace in an index. Namespaces let you partition data within an index and are essential for implementing multitenancy when you need to isolate the data of each customer or user. If an ID already exists, upserting overwrites the entire document or record. To change only part of one, update it.
Upserts consume write units (WUs). See Understand Pinecone cost for how upsert cost is calculated. To control costs when ingesting large datasets (10,000,000+ documents or records), use import instead of upsert.

Upsert documents

Documents are the unit of data in a document index. Each field in a document is indexed according to the configuration you declared for it in the schema, not just its type. For example, a string field can be indexed for BM25 with the full_text_search config, and a separate dense_vector field can store vector values you provide at upsert time. A string field can also declare embed or sparse_embed so Pinecone embeds its text with integrated embedding. The semantic_text type isn’t used in document schemas. It appears only when you describe a legacy integrated index. The following example upserts two documents into the articles namespace with the Documents API. Each document is indexed for BM25 ranking on body. The category field isn’t declared in the schema, so it’s stored as metadata and automatically indexed for filtering:
The Documents API requires API version 2026-07 or later. The vector index and legacy integrated index examples also work on earlier stable versions.
The schema declares only ranking fields: string fields with full_text_search, embed, or sparse_embed, plus dense_vector and sparse_vector fields. Any other field you upsert is stored on the document as metadata, returned with include_fields, and indexed for filtering. Field names must be unique, non-empty strings of up to 64 bytes. They can’t start with _, which is reserved for system fields such as _id and _score, or with $, which is reserved for filter operators. Upsert replaces the whole document for a given _id. To change individual fields, see Update documents. For document, field, and request size limits, see Upsert limits. For more examples and the response schema, see Full-text search.

Upsert dense vectors

To upsert dense vectors into a document index, use the Upsert documents operation:
  • Specify the namespace to upsert into. If the namespace doesn’t exist, it’s created. To use the default namespace, set the namespace to "__default__".
  • Format your input data as documents, each with the following:
    • An _id field with a unique document identifier for the index namespace.
    • The dense_vector field declared in the index schema, with the vector values. This example uses a field named embedding.
    • Optionally, other fields, which are stored as metadata. When you search the index, you can use metadata to filter search results.

Upsert sparse vectors

Upsert sparse vectors when your data is encoded by a learned sparse model, such as pinecone-sparse-english-v0, or when your application generates the sparse vectors itself. For BM25 keyword search over raw text without managing a model, see Upsert documents.
To upsert sparse vectors into a document index, use the Upsert documents operation:
  • Specify the namespace to upsert into. If the namespace doesn’t exist, it’s created. To use the default namespace, set the namespace to "__default__".
  • Format your input data as documents, each with the following:
    • An _id field with a unique document identifier for the index namespace.
    • The sparse_vector field declared in the index schema, with indices and values arrays. This example uses a field named sparse_embedding.
    • Optionally, other fields, which are stored as metadata. When you search the index, you can use metadata to filter search results.
For example, the following code upserts sparse vector representations of sentences related to the term “apple”, with the source text and additional fields stored as metadata:

Upsert in batches

To control costs when ingesting large datasets (10,000,000+ records), use import instead of upsert.
Send upserts in batches to help increase throughput.
  • When upserting documents, a request can contain up to 1,000 documents and 2 MB. In Python, index.documents.batch_upsert splits a larger list into batches, sends them in parallel, and halves any batch the server rejects as too large.
  • When upserting records with vectors, a batch should be as large as possible (up to 1,000 records) without exceeding the max request size of 2 MB. The number of records that fit in one batch depends on the vector dimension and metadata size:
  • When upserting text for Pinecone to embed, a batch can contain up to 96 records or documents. This limit comes from the hosted embedding models used during integrated embedding rather than the batch size limit for upserting raw vectors.

Upsert in parallel

Python SDK v6.0.0 and later provide async methods for use with asyncio. Asyncio support lets you use Pinecone with async web frameworks such as FastAPI, Quart, and Sanic. For details, see Async requests.
Send multiple upserts in parallel to help increase throughput. Each upsert call blocks until the response arrives, so send several at once.
In Python, batch_upsert sends batches in parallel. Set max_concurrency to cap the number of requests in flight. In JavaScript and Go, send the batches concurrently yourself:

Python SDK with gRPC

The Python SDK with gRPC can upsert faster. Unlike REST, gRPC multiplexes requests, so it handles many requests in parallel without head-of-line blocking. You can also pass retry strategies to the gRPC SDK, including exponential backoff. The gRPC client supports vector indexes only. For a document index, use the standard client. gRPC support is included in the base pinecone package, and upsert, query, fetch, and delete use the same syntax as the standard SDK. To use it, import the pinecone.grpc subpackage and target an index as usual:
Python
To send multiple upserts in parallel, use upsert_async, which returns a future for each request:
Python
Upserts through the gRPC SDK can hit write throttling sooner. If this happens often, implement retry logic with exponential backoff.

Upsert limits

The limit for text is lower because Pinecone converts that text to vectors at upsert time with integrated embedding, and 96 is the max batch size of the hosted embedding models doing the conversion. The 40 KB filterable metadata limit doesn’t apply to full_text_search text fields.