Fire and forget python async/await
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python asyncio, "fire and forget" does not mean calling a coroutine and ignoring it. A coroutine object does nothing until it is awaited or scheduled. Real fire-and-forget behavior means creating a background task that the event loop can run independently.
The Correct Primitive: asyncio.create_task
If you are already inside an active event loop, the normal way to start a background coroutine is asyncio.create_task.
The key point is that send_metric starts running because it was scheduled as a task. If you had written send_metric("signup") without awaiting or scheduling it, nothing would happen except a warning later.
Why Keeping A Reference Still Matters
Many developers hear "fire and forget" and interpret it as "never store the task". That is risky.
A background task can fail with an exception. If nothing observes the task, the failure may surface only as a noisy log message or be easy to miss.
A better pattern is to keep a reference long enough to attach error handling.
This is still "fire and forget" in the sense that the caller does not await the result directly, but the task is no longer invisible.
Fire And Forget Is Not A Process Boundary
Background tasks only live as long as the event loop lives. If your program exits immediately after scheduling a task, the task may never finish.
This often prints nothing because main ends and the event loop shuts down before the background task completes.
So real fire-and-forget inside one process still requires the process to stay alive long enough for the task to run.
Good Use Cases
This pattern is reasonable for lightweight side work such as:
- sending metrics
- refreshing a cache
- writing a non-critical audit record
- notifying another internal service
It is a poor fit for work that must succeed even if the current request, process, or event loop ends. For durable background jobs, use a queue, worker process, or external job system instead.
Structured Alternative
Sometimes the best answer is not fire-and-forget at all. If the task matters, gather it explicitly or manage it inside a task group.
This is not fire-and-forget, but it is often safer because failures and completion are explicit.
Avoid Blocking Work In The Event Loop
If the background work is CPU-bound or blocking, create_task is not enough because the coroutine may still block the loop internally. In that case, run blocking work in an executor or a separate worker.
This is often the right fire-and-forget pattern when the code you need to run is not asynchronous in the first place.
Common Pitfalls
The biggest mistake is creating a coroutine object and assuming it is already running. Coroutines must be awaited or scheduled.
Another issue is scheduling a task and then letting the program exit immediately. Fire-and-forget does not survive event-loop shutdown.
Developers also often ignore exceptions from background tasks. If the work matters at all, attach logging or some form of supervision.
Finally, do not use in-process fire-and-forget for durable business-critical work. If the task must outlive the request or the process, use a real job queue.
Summary
- In Python
asyncio, fire-and-forget means scheduling a coroutine withasyncio.create_task, not merely calling it. - Keep a reference or callback if you need to observe exceptions.
- Background tasks stop when the event loop stops.
- Use executors for blocking work that should run in the background.
- For important or durable jobs, prefer an external worker or queue over in-process fire-and-forget.

