tezvyn:

How do you send an email without blocking a FastAPI request?

AI-drafted, machine-checkedSource: fastapi.tiangolo.combeginner

Tests knowledge of FastAPI's BackgroundTasks for post-response work. Strong answer: import it, inject into the endpoint, define a task function, and call add_task before returning.

RED FLAG

Recommending raw asyncio.create_task or insisting Celery is required.

WHAT THIS TESTS: This question checks whether you understand how to offload non-blocking work in FastAPI without introducing unnecessary infrastructure. The interviewer wants to see that you know BackgroundTasks exists, understand when it is sufficient versus when you need a proper task queue, and can explain the request lifecycle correctly. Email sending typically takes one to three seconds due to SMTP handshakes, so blocking the response path creates a poor user experience and wastes worker time.

A GOOD ANSWER COVERS: First, import BackgroundTasks from fastapi. Second, declare a background_tasks parameter with the type BackgroundTasks in your path operation function signature. Third, define a separate task function that accepts the data it needs, such as the recipient address and subject line, and performs the email send inside it. Fourth, inside the endpoint call background_tasks.add_task(your_task_function, arg1, arg2) before you return the response. FastAPI will execute the task after the response is sent but while the request context is still available. Mention that BackgroundTasks uses Starlette's background task runner under the hood and requires no extra dependencies.

COMMON WRONG ANSWERS: A red flag is suggesting asyncio.create_task inside the endpoint because that schedules a coroutine on the event loop but does not guarantee execution if the server drops the connection or the loop closes. Another red flag is immediately jumping to Celery or RabbitMQ for a single confirmation email; while those are valid at scale, they add operational complexity that is unnecessary for this specific scenario. Also avoid saying you would return HTTP 202 Accepted unless you are actually handing the job to an external queue; BackgroundTasks still runs inside the same process after the response, so 202 is misleading.

LIKELY FOLLOW-UPS: The interviewer may ask what happens if the background task raises an exception. You should note that it does not affect the already-sent response, but errors are logged and the task fails silently from the client perspective. They might also ask when to prefer Celery over BackgroundTasks; the cutoff is usually when you need retries, persistence across server restarts, or distributed workers. Another follow-up is whether BackgroundTasks blocks the event loop; since the task runs in the same process, a CPU-bound task would block, so background tasks should remain IO-bound and lightweight.

ONE CONCRETE EXAMPLE: Imagine an endpoint POST /users that creates a user and returns the user object. You define a function send_confirmation_email(email: str, token: str) that connects to an SMTP server. Inside the endpoint you write background_tasks.add_task(send_confirmation_email, user.email, token) and then return user. The client receives the JSON payload in roughly fifty milliseconds while the email send proceeds afterward. If the SMTP call fails, the user already has their success response.

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.