Do not perform blocking I/O or other long-running synchronous work on asyncio’s event loop (especially in async client construction). Offload to worker threads (e.g., asyncio.to_thread) and prefer lazy credential/platform resolution protected by an async lock.

Also, when canceling/ending streamed responses, ensure you deterministically close the local stream before issuing any remote cancel call, and structure async generator cleanup so sessions/resources are released even if iteration terminates early.

Example pattern (lazy thread offload + guarded resolution):

import asyncio

class AsyncClient:
    def __init__(self, *, use_sigv4: bool):
        self._use_sigv4 = use_sigv4
        self._botocore_credentials = None
        self._creds_lock = asyncio.Lock()

    async def _get_credentials(self):
        if not self._use_sigv4:
            return None
        if self._botocore_credentials is None:
            async with self._creds_lock:
                if self._botocore_credentials is None:
                    # Offload blocking credential lookup/refresh work.
                    self._botocore_credentials = await asyncio.to_thread(_get_default_credentials)
        return self._botocore_credentials

    async def _prepare_request(self, request):
        creds = await self._get_credentials()
        _sign_httpx_request(request, creds, region="us-east-1")

Example pattern (stream cancel ordering):

def cancel_stream(stream, cancel_api):
    stream.close()              # close local stream first
    return cancel_api(stream.response_id)

Practical checklist: