Are Android's BroadcastReceivers started in a new thread?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
No, a normal Android BroadcastReceiver does not start on a fresh worker thread by default. Its onReceive() callback usually runs on the main thread of your app process. That is why receiver code must return quickly and should hand off real work to another component instead of blocking in place.
What Thread onReceive() Runs On
The default mental model is simple: a broadcast arrives, Android enters your process, and calls onReceive() on the main thread.
If you log the thread name, you will typically see the app's main thread rather than a dedicated background worker.
This matters because the main thread is also responsible for UI responsiveness and other app event handling.
Why the Main-Thread Behavior Is Important
A receiver is not designed to be a long-running job processor. Its job is to react quickly to an event and then return.
Bad pattern:
That can stall the main thread, make the app unresponsive, and cause the system to treat the receiver as misbehaving.
The safer pattern is:
- inspect the broadcast
- decide what should happen
- schedule or delegate the actual work
- return quickly
Use goAsync() for Short Deferred Work
If you need a little more time after onReceive() returns, Android provides goAsync().
This is useful for short asynchronous continuation. It is not a replacement for a proper background job scheduler. You must call finish() when the work is done.
Prefer WorkManager for Real Background Jobs
If a broadcast should trigger actual processing, use WorkManager instead of doing the whole job inside the receiver.
This is usually the right production design because WorkManager handles retries, constraints, process death, and scheduling more safely than a raw thread.
Ordered Broadcasts Do Not Change the Core Rule
Even with ordered broadcasts, the default callback is still not a magic worker-thread execution model. Ordered broadcasts change delivery semantics, not the basic rule that onReceive() should stay short and non-blocking.
Think of the receiver as an event entry point, not as a service.
Dynamic and Manifest Registration
Whether the receiver is registered in the manifest or registered dynamically in code, the same design guidance still applies: do not assume heavy work belongs in onReceive().
If the process is not running, Android may start it to deliver the broadcast. That does not mean the receiver suddenly owns a special background execution context. It simply means the process is active so the callback can run.
Common Pitfalls
- Assuming a
BroadcastReceiverautomatically runs on a worker thread. - Doing network, disk, or database work directly inside
onReceive(). - Using
goAsync()and forgetting to callfinish(). - Spawning ad hoc threads for durable work that belongs in
WorkManager. - Treating receiver code as if it were a long-lived background service.
Summary
- A normal Android
BroadcastReceiveris not started on a new thread by default. - '
onReceive()usually executes on the main thread.' - Receiver logic should be quick and non-blocking.
- Use
goAsync()only for short follow-up work. - For real background processing, delegate to
WorkManageror another structured background API.

