fastapi-tasks
Introduction
fastapi-tasks is a Python library for managing background tasks in FastAPI applications with precise timing control.
Unlike FastAPI's built-in BackgroundTasks which only runs tasks after the response is sent, fastapi-tasks gives you
fine-grained control over when your background tasks execute:
- Immediately - Task starts right away, concurrently with your endpoint
- After Route - Task is scheduled after your endpoint completes, before the response is sent (fire-and-forget)
- After Response - Task is scheduled after the response is sent to the client
Features:
- Precise timing control - Choose exactly when your background tasks run
- Task shielding - Protect critical tasks from cancellation during shutdown
- Error handling - Custom error handlers for graceful failure recovery
- Full async support - Works with both sync and async task functions
- Type safe - Full type hints and generic support
- Lightweight - Built on top of
anyiowith minimal dependencies
Installation
pip install fastapi-tasks
Quickstart
All you need to do is call add_tasks(app) and use the Tasks dependency in your endpoints.
from fastapi import FastAPI
from fastapi_tasks import Tasks, add_tasks
app = FastAPI()
add_tasks(app) # important! add tasks support to your app
async def send_welcome_email(email: str) -> None:
# your email sending logic here
...
async def log_analytics(event: str, user_id: int) -> None:
# your analytics logic here
...
@app.post("/users")
async def create_user(email: str, tasks: Tasks) -> dict:
user_id = 1 # create user in database
# Schedule tasks with different timing
tasks.schedule(send_welcome_email, email) # starts immediately
tasks.after_route.schedule(log_analytics, "user_created", user_id) # after endpoint
tasks.after_response.schedule(log_analytics, "response_sent", user_id) # after response
return {"user_id": user_id}
Timing Modes
Important: All background tasks are fire-and-forget. They are scheduled at specific points but don't block the response.
| Mode | When it's scheduled | Use case |
|---|---|---|
tasks.schedule() |
Immediately (concurrent) | Fire-and-forget, non-blocking operations |
tasks.after_route.schedule() |
After endpoint returns, before response | Cleanup, logging (doesn't block response) |
tasks.after_response.schedule() |
After response sent | Notifications, analytics, emails |
Timing Visualization
Request arrives
│
├─► tasks.schedule() ──────────────────────► Scheduled immediately (concurrent)
│
▼
Endpoint function executes
│
▼
Endpoint returns
│
├─► tasks.after_route.schedule() ─────────► Scheduled here (fire-and-forget)
│
▼
Response sent to client
│
├─► tasks.after_response.schedule() ──────► Scheduled here
│
▼
Request complete
Task Configuration
You can configure tasks with a name, shielding, and custom error handlers:
async def on_task_error(task, exception: Exception) -> None:
print(f"Task {task.config.name} failed: {exception}")
@app.post("/orders")
async def create_order(order_id: int, tasks: Tasks) -> dict:
# Configure task with name and error handler
tasks.task(
name="process_order",
shield=True, # protect from cancellation
on_error=on_task_error,
).schedule(process_order, order_id)
return {"order_id": order_id}
Configuration Options
| Option | Type | Description |
|---|---|---|
name |
str | None |
Task name for logging and debugging |
shield |
bool | None |
Protect task from cancellation during shutdown |
on_error |
Callable | None |
Custom error handler for task failures |
Shielding Critical Tasks
When your application shuts down, running tasks are cancelled. Use shield=True to protect critical tasks:
@app.post("/payments")
async def process_payment(payment_id: int, tasks: Tasks) -> dict:
# This task will complete even if the server is shutting down
tasks.task(shield=True).schedule(finalize_payment, payment_id)
return {"status": "processing"}
Sync and Async Tasks
fastapi-tasks works with both sync and async functions. Sync functions are automatically
run in a thread pool to avoid blocking the event loop:
def sync_task(data: str) -> None:
# This runs in a thread pool
time.sleep(1)
print(f"Processed: {data}")
async def async_task(data: str) -> None:
# This runs in the event loop
await asyncio.sleep(1)
print(f"Processed: {data}")
@app.post("/process")
async def process(tasks: Tasks) -> dict:
tasks.schedule(sync_task, "sync data") # runs in thread pool
tasks.schedule(async_task, "async data") # runs in event loop
return {"status": "ok"}
Error Handling
By default, task exceptions are logged but don't affect the response. You can provide custom error handlers:
from fastapi_tasks import Task
async def handle_error(task: Task, error: Exception) -> None:
# Log to your error tracking service
await sentry_sdk.capture_exception(error)
# Or retry the task, send alerts, etc.
@app.post("/risky")
async def risky_operation(tasks: Tasks) -> dict:
tasks.task(on_error=handle_error).schedule(might_fail)
return {"status": "started"}
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for fastapi-tasks 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fastapi_tasks-0.1.0.tar.gz | 96.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_tasks-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 104.0 kB
Release files / fastapi_tasks-0.1.0.tar.gz
| Download URL | fastapi_tasks-0.1.0.tar.gz |
|---|---|
| Size | 96.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
05f2fea58ecd483f5584656756bae38031fa447aa58c69391f7c0102b219facb
|
|
BLAKE2b-256 checksum How to use checksums |
585aea664c0c2ae398e864e07d043b5588f7b5e9450b90c82540c0b441eb88bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / fastapi_tasks-0.1.0-py3-none-any.whl
| Download URL | fastapi_tasks-0.1.0-py3-none-any.whl |
|---|---|
| Size | 7.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d4ce38b904b720bbe33a0aa034950116a48ae9d4e9e8ad349ffd2a1bf94e3306
|
|
BLAKE2b-256 checksum How to use checksums |
e99463d015cd58b27d01f40799c38f41e1ca65c0b5958ccdcbce4c27f519506e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for fastapi-tasks 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.