FastAPI: difference between run_in_executor and run_in_threadpool

David Y.

The Problem

In FastAPI, what’s the difference between run_in_executor and run_in_threadpool? As far as I can tell, both are used to execute a task in another thread. When should I use one over the other?

The Solution

Both run_in_executor and run_in_threadpool are used to run synchronous code (also called blocking code) in an asynchronous application without blocking the event loop. run_in_executor is a relatively low-level operation, originating in Python’s asyncio library, whereas run_in_threadpool comes from Starlette, the ASGI framework underlying FastAPI.

As a result, run_in_threadpool is simpler to use at the cost of flexibility, and run_in_executor is more flexible at the cost of increased complexity. Consider the following two code examples:

# Using run_in_executor import asyncio from concurrent.futures import ThreadPoolExecutor def sync_function(argument1, argument2): # logic for the sync function here pass async def main(): loop = asyncio.get_running_loop() with ThreadPoolExecutor() as pool: result = await loop.run_in_executor(pool, sync_function, 'argument1', 'argument2')
# Using run_in_threadpool from fastapi import FastAPI from starlette.concurrency import run_in_threadpool app = FastAPI() def sync_function(argument1, argument2): # logic for the sync function here pass async def example_route(): result = await run_in_threadpool(sync_function, 'argument1', 'argument2')

As we can see, the run_in_threadpool code is simpler – unlike the run_in_executor code, it does not require us to specify an executor, as it will always use the default executor. Most of the time, this is what we want – run_in_threadpool is integrated with FastAPI’s design and is the recommended approach for most use cases.

However, if we have a complicated application that needs to integrate a variety of disparate synchronous systems, we may want the additional control that run_in_executor provides. For example, some applications may benefit from using ProcessPoolExecutor instead of ThreadPoolExecutor.

Loved by over 4 million developers and more than 90,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

Share on Twitter
Bookmark this page
Ask a questionJoin the discussion

Related Answers

A better experience for your users. An easier life for your developers.

© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.