Migrating from v8.x to v9.x¶
v9 is a ground-up rewrite focused on simplicity, performance, and type safety. This guide covers the breaking changes and shows you the v9 equivalent for each v8 pattern.
Key changes¶
1. Namespace pattern for control-plane operations¶
In v8, control-plane methods lived directly on the Pinecone client:
# v8
pc.create_index(name="my-index", dimension=1536, metric="cosine", spec=...)
indexes = pc.list_indexes()
pc.delete_index("my-index")
In v9, they are grouped under namespace properties:
# v9
pc.indexes.create(name="my-index", dimension=1536, metric="cosine", spec=...)
indexes = pc.indexes.list()
pc.indexes.delete("my-index")
The same pattern applies to collections, backups, and inference:
pc.collections.create(...)
pc.backups.list()
pc.inference.embed(...)
2. Async client rename¶
PineconeAsyncio is renamed to AsyncPinecone. The old name still works but is
deprecated and will be removed in a future release.
# v8
from pinecone import PineconeAsyncio
async with PineconeAsyncio(api_key="...") as pc:
...
# v9
from pinecone import AsyncPinecone
async with AsyncPinecone(api_key="...") as pc:
...
3. Response models¶
v8 returned a mix of plain dicts, dataclass models, and bespoke objects. v9 returns msgspec.Struct instances.
Field access is straightforward—idx.name, idx.dimension—but the objects are immutable.
dict() no longer works; use msgspec.structs.asdict(idx) if you need a dict.
# v9 — field access is unchanged
idx = pc.indexes.describe("my-index")
print(idx.name) # works
print(idx.dimension) # works
print(dict(idx)) # TypeError — structs are not dict-convertible
4. HTTP transport: httpx replaces urllib3¶
The SDK uses httpx instead of urllib3. Retry behavior is now configured
with RetryConfig passed at client construction:
# v8 — retry parameters were keyword args on the client
pc = Pinecone(api_key="...", retries=3)
# v9
from pinecone import Pinecone, RetryConfig
pc = Pinecone(
api_key="...",
retry_config=RetryConfig(max_retries=3, backoff_factor=1.5),
)
5. gRPC: Rust extension replaces grpcio¶
GrpcIndex is now backed by a compiled Rust extension instead of the Python grpcio
package. You do not need to install grpcio or grpcio-tools. The interface—upsert,
query, fetch, delete—is unchanged.
# v9 — interface is the same; no grpcio dependency required
index = pc.index("my-index", grpc=True)
index.upsert(vectors=[...])
6. Import paths¶
Most public classes are still importable directly from pinecone:
from pinecone import Pinecone, AsyncPinecone, Index, GrpcIndex
from pinecone import ServerlessSpec, PodSpec
from pinecone import ConflictError, NotFoundError, ForbiddenError
Deep imports (from pinecone.core.client.api...) are no longer supported. Use the
top-level package instead.
7. Python version requirement¶
Python 3.9 support is dropped. The minimum supported version is Python 3.10.
8. Removal of the pinecone_plugins.assistant import path¶
In v8, the assistant SDK shipped as a separate plugin package
(pinecone-plugin-assistant) installed alongside pinecone. Code
imported model classes from pinecone_plugins.assistant.*:
# v8
from pinecone_plugins.assistant.models import (
AssistantModel, ContextOptions, Message, FileModel,
)
from pinecone_plugins.assistant.models.chat import ChatResponse
In v9 the assistant API is built into the main pinecone package
and the pinecone_plugins import tree has been removed. All
classes are now reachable from pinecone.models.assistant under
either the canonical name or a legacy alias.
Replace each legacy import with the canonical path:
v8 import path |
v9 import path |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
No replacement — see note below. |
What does not change. Method-call backcompat is preserved:
# Both v8 and v9
pc = Pinecone(api_key="...")
pc.assistant.create_assistant("my-assistant") # works in v9
pc.assistant.list_assistants() # works in v9
assistant = pc.assistant.describe_assistant("my-assistant")
assistant.upload_file(file_path="report.pdf") # works in v9
assistant.chat(messages=[...]) # works in v9
The pc.assistant namespace is preserved and singular/plural
forms (pc.assistant and pc.assistants) are interchangeable.
Legacy method names like create_assistant, delete_assistant,
list_assistants_paginated, etc. continue to work alongside the
canonical pc.assistants.create, .delete, .list_page.
The legacy plugin class is removed. Code that manually
instantiated the plugin (Assistant(config, client_builder) from
pinecone_plugins.assistant.assistant.assistant) has no v9
equivalent — the plugin discovery system was retired and
pc.assistant is now a property on the Pinecone client. Such
code must be rewritten to use pc.assistants directly.
Environment variables PINECONE_PLUGIN_ASSISTANT_CONTROL_HOST
and PINECONE_PLUGIN_ASSISTANT_DATA_HOST are no longer consulted.
To target a non-prod control plane, pass host= to the Pinecone
constructor or set PINECONE_HOST. The data-plane host is
discovered automatically from the host field of the
describe_assistant response.
9. Partial-success contract for batched upsert¶
index.upsert(...) gains batch_size, max_concurrency, and
show_progress kwargs that match v8’s signature on the
surface — but the failure behaviour changed.
v8 behaviour. idx.upsert(vectors=[...], batch_size=N)
raised on the first batch failure. Successful batches were
lost; subsequent batches were not attempted.
v9 behaviour. Batches are submitted concurrently
(max_concurrency=4 default; range 1–64). Per-batch HTTP
retries happen automatically via
RetryConfig. Failures that exceed the
retry budget are captured on the returned
UpsertResponse rather than raised.
The response now carries total_item_count,
failed_item_count, total_batch_count,
successful_batch_count, failed_batch_count,
errors: list[BatchError], plus convenience properties
has_errors, error_count, success_count, and
failed_items.
Code that wraps a batched upsert in try/except will silently
undercount in v9 unless updated:
# v8 — relied on exception to roll back
try:
idx.upsert(vectors=batch, batch_size=100)
except Exception:
rollback()
# v9 — inspect response.has_errors instead
response = idx.upsert(vectors=batch, batch_size=100)
if response.has_errors:
# Optionally retry only the failures:
idx.upsert(vectors=response.failed_items, batch_size=100)
# …or roll back if any failure is unacceptable
Single-request upsert (batch_size=None, the default) keeps
its v8 raise-on-failure semantics. The contract change applies
only when batch_size is set.
The same partial-success contract applies to
AsyncIndex.upsert(...) and GrpcIndex.upsert(...).
v8 → v9 migration table¶
Operation |
v8 |
v9 |
|---|---|---|
Create index |
|
|
List indexes |
|
|
Describe index |
|
|
Delete index |
|
|
Configure index |
|
|
Check index exists |
|
|
Get data-plane index |
|
|
Get gRPC index |
|
|
Create collection |
|
|
List collections |
|
|
Delete collection |
|
|
Upsert vectors |
|
|
Query vectors |
|
|
Fetch vectors |
|
|
Delete vectors |
|
|
Async client |
|
|
Retry config |
|
|
Convert response to dict |
|
|
Embed text |
|
|
Legacy aliases¶
The following aliases remain importable from pinecone but are deprecated:
Deprecated name |
Canonical name |
|---|---|
|
|
|
|
|
|
|
|
These aliases will be removed in a future major release. Update your code to use the canonical names.