# Async Python client
## When
Your app is asyncio-based (FastAPI, async workers) and makes many Pinecone calls. The async client avoids blocking the event loop on network I/O.
## Pattern
```
import asyncio
from pinecone import PineconeAsyncio
async def main():
async with PineconeAsyncio() as pc:
index = pc.Index("quickstart")
await index.upsert(vectors=[{"id": "vec1", "values": [0.1, 0.2, 0.3]}])
res = await index.query(vector=[0.1, 0.2, 0.3], top_k=5)
asyncio.run(main())
```
Like the sync client, it reads `PINECONE_API_KEY` from the environment when constructed with no arguments.
## Rules
1. Do not mix sync and async clients against the same workload in one process; pick one per application.
2. Bound concurrency with a semaphore. Unbounded `asyncio.gather` over thousands of upserts 429s exactly like unbounded threads.
3. Close the client (`async with` or explicit close) so connections do not leak across requests in long-lived servers.
## Trap
Wrapping the sync client in `run_in_executor` everywhere instead of using the async client. It works until thread-pool starvation makes latency weird and hard to diagnose. Use the client built for the job.