# FastAPI: difference between run_in_executor and run_in_threadpool

**URL:** https://sentry.io/answers/fastapi-difference-between-run-in-executor-and-run-in-threadpool/

---

## 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:

```python
# 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')
```

```python
# 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](https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.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`](https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor) instead of `ThreadPoolExecutor`.

---

*Source: [sentry.io/answers/fastapi-difference-between-run-in-executor-and-run-in-threadpool/](https://sentry.io/answers/fastapi-difference-between-run-in-executor-and-run-in-threadpool/)*
