How do you structure concurrent API calls with asyncio.gather in FastAPI?

Tests FastAPI async concurrency. Strong answer: async def endpoint with two async HTTP requests in asyncio.gather, cutting total latency from sum to max of the two. Red flag: using sync clients or threads instead of async I/O.
WHAT THIS TESTS: This tests whether you understand FastAPI's concurrency model for I/O-bound operations. FastAPI runs on Starlette and Uvicorn, which use an asyncio event loop. The interviewer wants to know if you grasp that independent network calls should not block each other and that asyncio.gather is the idiomatic tool for fanning out multiple awaitables. They also care whether you can articulate the latency win and avoid blocking the loop with synchronous libraries.
A GOOD ANSWER COVERS: First, declare the path operation with async def so FastAPI treats it as a coroutine. Second, use an async-capable HTTP client such as httpx.AsyncClient or aiohttp rather than synchronous requests. Third, structure the two fetches as independent coroutines and pass them to asyncio.gather to schedule them concurrently on the event loop. Fourth, explain the performance benefit in concrete terms: if API A takes 300 ms and API B takes 250 ms, sequential execution takes roughly 550 ms while concurrent execution takes roughly 300 ms, the maximum of the two. Fifth, mention error handling, noting that gather raises the first exception encountered unless return_exceptions=True is passed, and that you should consider timeouts via asyncio.wait_for or the client itself.
COMMON WRONG ANSWERS: A major red flag is using the standard synchronous requests library inside an async endpoint; this blocks the event loop and stalls all other requests. Another mistake is suggesting threading or multiprocessing for this use case, confusing parallelism with concurrency. Some candidates forget to await the gather result or try to use gather with regular synchronous functions, which does not create true concurrency. Proposing a global event loop manipulation or nest_asyncio is also a signal of weak asyncio fundamentals.
LIKELY FOLLOW-UPS: The interviewer may ask what happens if one call fails, how you would apply a timeout to both calls, or how you would limit concurrency if the endpoint needed to fan out to fifty APIs instead of two. They might also ask how this changes under heavy load or whether you would cache one of the responses. Be ready to discuss backpressure and connection pooling with an async HTTP client.
ONE CONCRETE EXAMPLE: Imagine an endpoint GET /dashboard that needs user profile data from a CRM and notification count from a messaging service. You write async def get_dashboard():, create an httpx.AsyncClient, then define coroutines fetch_crm() and fetch_messaging(). You call results = await asyncio.gather(fetch_crm(), fetch_messaging()). The event loop sends both requests, suspends while waiting for I/O, and resumes as each response arrives. Total latency is dictated by the slower service, not the sum.
Source: fastapi.tiangolo.com
Read the original → fastapi.tiangolo.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.